From 695bc41007c1a46901fc6824db47af7bc5deebac Mon Sep 17 00:00:00 2001 From: Dolph Mathews Date: Wed, 15 Oct 2014 17:06:59 +0000 Subject: [PATCH] add v3 API documentation These are the restructuredtext documents produced as a result of the following changes (originally proposed to openstack/identity-api): * Convert markdown to restructured text: https://review.openstack.org/#/c/128676/ * Split HTTP methods & resources from section titles: https://review.openstack.org/#/c/128690/ * And a few minor content changes to comply with doc8: https://review.openstack.org/#/c/128693/ This change also adds doc8 validation to the new api/ directory. Change-Id: Ia575cf8f00558503bf6b4bea11836ddc1d2f1188 --- api/identity-api-v3-os-endpoint-policy.rst | 261 + api/identity-api-v3-os-ep-filter-ext.rst | 680 +++ api/identity-api-v3-os-federation-ext.rst | 1400 ++++++ api/identity-api-v3-os-inherit-ext.rst | 344 ++ api/identity-api-v3-os-kds-ext.rst | 524 ++ api/identity-api-v3-os-oauth1-ext.rst | 535 ++ api/identity-api-v3-os-revoke-ext.rst | 175 + api/identity-api-v3-os-simple-certs-ext.rst | 197 + api/identity-api-v3-os-trust-ext.rst | 542 +++ api/identity-api-v3.rst | 4845 +++++++++++++++++++ specs/template.rst | 3 + tox.ini | 2 +- 12 files changed, 9507 insertions(+), 1 deletion(-) create mode 100644 api/identity-api-v3-os-endpoint-policy.rst create mode 100644 api/identity-api-v3-os-ep-filter-ext.rst create mode 100644 api/identity-api-v3-os-federation-ext.rst create mode 100644 api/identity-api-v3-os-inherit-ext.rst create mode 100644 api/identity-api-v3-os-kds-ext.rst create mode 100644 api/identity-api-v3-os-oauth1-ext.rst create mode 100644 api/identity-api-v3-os-revoke-ext.rst create mode 100644 api/identity-api-v3-os-simple-certs-ext.rst create mode 100644 api/identity-api-v3-os-trust-ext.rst create mode 100644 api/identity-api-v3.rst diff --git a/api/identity-api-v3-os-endpoint-policy.rst b/api/identity-api-v3-os-endpoint-policy.rst new file mode 100644 index 00000000..5028930f --- /dev/null +++ b/api/identity-api-v3-os-endpoint-policy.rst @@ -0,0 +1,261 @@ +OpenStack Identity API v3 OS-ENDPOINT-POLICY Extension +====================================================== + +This extension provides associations between service endpoints and +policies that are already stored in the Identity server and referenced +by policy ID. Such associations enable an endpoint to request the +appropriate policy for itself. Three types of association are supported: + +- A policy associated to a specific endpoint +- A policy associated to any endpoint of a given service type in a + given region +- A policy associated to any endpoint of a given service type + +When an endpoint requests the appropriate policy for itself, the +extension will look for an association *in the order given above* (which +is essentially in order from most specific to least specific) and select +the first one it finds. For region associations, any parent regions will +also be examined in ascending order. No combination of polices will +occur. + +Policy-Endpoint Associations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Create association with endpoint +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + PUT /policies/{policy_id}/OS-ENDPOINT-POLICY/endpoints/{endpoint_id} + +Creates an association between the policy and the endpoint. If another +association already existed for the specified endpoint, this will +replace that association. Any body supplied with this API will be +ignored. + +Response: + +:: + + Status: 204 No Content + +Check association with endpoint +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /policies/{policy_id}/OS-ENDPOINT-POLICY/endpoints/{endpoint_id} + +Verifies the existence of an association between a policy and an +endpoint. A HEAD version of this API is also supported. + +Response: + +:: + + Status: 204 No Content + +Delete association with endpoint +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + DELETE /policies/{policy_id}/OS-ENDPOINT-POLICY/endpoints/{endpoint_id} + +Deletes an association between the policy and the endpoint. + +Response: + +:: + + Status: 204 No Content + +Create association with service +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + PUT /policies/{policy_id}/OS-ENDPOINT-POLICY/services/{service_id} + +Creates an association between the policy and the service. If another +association already existed for the specified service, this will replace +that association. Any body supplied with this API will be ignored. + +Response: + +:: + + Status: 204 No Content + +Check association with service +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /policies/{policy_id}/OS-ENDPOINT-POLICY/services/{service_id} + +Verifies the existence of an association between a policy and a service. +A HEAD version of this API is also supported. + +Response: + +:: + + Status: 204 No Content + +Delete association with service +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + DELETE /policies/{policy_id}/OS-ENDPOINT-POLICY/services/{service_id} + +Deletes an association between the policy and the service. + +Response: + +:: + + Status: 204 No Content + +Create association with service in a region +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + PUT /policies/{policy_id}/OS-ENDPOINT-POLICY/services/{service_id}/regions/{region_id} + +Creates an association between the policy and the service in the given +region. If another association already existed for the specified service +and region, this will replace that association. Any body supplied with +this API will be ignored. + +Response: + +:: + + Status: 204 No Content + +Check association with service in a region +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /policies/{policy_id}/OS-ENDPOINT-POLICY/services/{service_id}/regions/{region_id} + +Verifies the existence of an association between a policy and a service +in the given region. A HEAD version of this API is also supported. + +Response: + +:: + + Status: 204 No Content + +Delete association with service in a region +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + DELETE /policies/{policy_id}/OS-ENDPOINT-POLICY/services/{service_id}/regions/{region_id} + +Deletes an association between the policy and the service in the given +region. + +Response: + +:: + + Status: 204 No Content + +List effective endpoint associations for policy +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /policies/{policy_id}/OS-ENDPOINT-POLICY/endpoints + +Returns all the endpoints that are currently associated with a specific +policy via any of the association methods. + +Response: + +:: + + Status: 200 OK + + { + "endpoints": [ + { + "id": "--endpoint-id--", + "interface": "public", + "links": { + "self": "http://identity:35357/v3/endpoints/--endpoint-id--" + }, + "region": "north", + "service_id": "--service-id--", + "url": "http://identity:35357/" + }, + { + "id": "--endpoint-id--", + "interface": "internal", + "links": { + "self": "http://identity:35357/v3/endpoints/--endpoint-id--" + }, + "region": "south", + "service_id": "--service-id--", + "url": "http://identity:35357/" + } + ], + "links": { + "next": null, + "previous": null, + "self": "http://identity:35357/v3/OS-ENDPOINT-POLICY/policies/{policy_id}/endpoints" + } + } + +Get effective policy associated with endpoint +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /endpoints/{endpoint_id}/OS-ENDPOINT-POLICY/policy + +Returns the policy that is currently associated with the given endpoint, +by working through the ordered sequence of methods of association. The +first association that is found will be returned. If the region of the +endpoint has a parent, then region associations will be examined up the +region tree in ascending order. + +Response: + +:: + + Status: 200 OK + + { + "policy": { + "blob": "--serialized-blob--", + "id": "--policy-id--", + "links": { + "self": "http://identity:35357/v3/policies/--policy-id--" + }, + "type": "--serialization-mime-type--" + } + } + +Check if a policy is associated with endpoint +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + HEAD /endpoints/{endpoint_id}/OS-ENDPOINT-POLICY/policy + +Checks if a policy is currently associated with the given endpoint. + +Response: + +:: + + Status: 200 OK + diff --git a/api/identity-api-v3-os-ep-filter-ext.rst b/api/identity-api-v3-os-ep-filter-ext.rst new file mode 100644 index 00000000..47a88c2c --- /dev/null +++ b/api/identity-api-v3-os-ep-filter-ext.rst @@ -0,0 +1,680 @@ +OpenStack Identity API v3 OS-EP-FILTER Extension +================================================ + +This extension enables creation of ad-hoc catalogs for each +project-scoped token request. To do so, this extension uses either +static project-endpoint associations or dynamic custom endpoints groups +to associate service endpoints with projects. + +What's New in Version 1.1 +------------------------- + +These features are not yet considered stable (expected September 4th, +2014). + +- Introduced support for Endpoint Groups + +API Resources +------------- + +*New in version 1.1* + +Endpoint Group +~~~~~~~~~~~~~~ + +Represents a dynamic collection of service endpoints having the same +characteristics, such as service\_id, interface, or region. Indeed, any +endpoint attribute could be used as part of a filter. + +A classic use case is to filter endpoints based on region. For example, +suppose a user wants to filter service endpoints returned in the service +catalog by region, the following endpoint group may be used: + +:: + + { + "endpoint_group": { + "description": "Example Endpoint Group", + "filters": { + "region_id": "e68c72" + }, + "name": "EP-GROUP-1" + } + } + +This implies an Endpoint Group with filtering criteria of the form: + +:: + + region_id = "e68c72" + +API +--- + +Project-Endpoint Associations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If a valid X-Auth-Token token in not present in the HTTP header and/or +the user does not have the right authorization a HTTP 401 Unauthorized +is returned. + +Create Association +^^^^^^^^^^^^^^^^^^ + +:: + + PUT /OS-EP-FILTER/projects/{project_id}/endpoints/{endpoint_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-EP-FILTER/1.0/rel/project_endpoint`` + +Modifies the endpoint resource adding an association between the project +and the endpoint. + +Response: + +:: + + Status: 204 No Content + +Check Association +^^^^^^^^^^^^^^^^^ + +:: + + HEAD /OS-EP-FILTER/projects/{project_id}/endpoints/{endpoint_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-EP-FILTER/1.0/rel/project_endpoint`` + +Verifies the existence of an association between a project and an +endpoint. + +Response: + +:: + + Status: 204 No Content + +List Associations for Project +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /OS-EP-FILTER/projects/{project_id}/endpoints + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-EP-FILTER/1.0/rel/project_endpoints`` + +Returns all the endpoints that are currently associated with a specific +project. + +Response: + +:: + + Status: 200 OK + { + "endpoints": [ + { + "id": "6fedc0", + "interface": "public", + "url": "http://identity:35357/", + "region": "north", + "links": { + "self": "http://identity:35357/v3/endpoints/6fedc0" + }, + "service_id": "1b501a" + }, + { + "id": "6fedc0", + "interface": "internal", + "region": "south", + "url": "http://identity:35357/", + "links": { + "self": "http://identity:35357/v3/endpoints/6fedc0" + }, + "service_id": "1b501a" + } + ], + "links": { + "self": "http://identity:35357/v3/OS-EP-FILTER/projects/{project_id}/endpoints", + "previous": null, + "next": null + } + } + +Delete Association +^^^^^^^^^^^^^^^^^^ + +:: + + DELETE /OS-EP-FILTER/projects/{project_id}/endpoints/{endpoint_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-EP-FILTER/1.0/rel/project_endpoint`` + +Eliminates a previously created association between a project and an +endpoint. + +Response: + +:: + + Status: 204 No Content + +Get projects associated with endpoint +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /OS-EP-FILTER/endpoints/{endpoint_id}/projects + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-EP-FILTER/1.0/rel/endpoint_projects`` + +Returns a list of projects that are currently associated with the given +endpoint. + +Response: + +:: + + Status: 200 OK + + { + "projects": [ + { + "domain_id": "1789d1", + "enabled": true, + "id": "263fd9", + "links": { + "self": "http://identity:35357/v3/projects/263fd9" + }, + "name": "a project name 1", + "description": "a project description 1" + }, + { + "domain_id": "1789d1", + "enabled": true, + "id": "61a1b7", + "links": { + "self": "http://identity:35357/v3/projects/61a1b7" + }, + "name": "a project name 2", + "description": "a project description 2" + } + ], + "links": { + "self": "http://identity:35357/v3/OS-EP-FILTER/endpoints/6fedc0/projects", + "previous": null, + "next": null + } + +} + +Endpoint Groups +~~~~~~~~~~~~~~~ + +*New in version 1.1* + +Required attributes: + +- ``name`` (string) + +User-facing name of the service. + +- ``filters`` (object) + +Describes the filtering performed by the endpoint group. The filter used +must be an ``endpoint`` property, such as ``interface``, ``service_id``, +``region_id`` and ``enabled``. Note that if using ``interface`` as a +filter, the only available values are ``public``, ``internal`` and +``admin``. + +Optional attributes: + +- ``description`` (string) + +User-facing description of the service. + +Create Endpoint Group Filter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + POST /OS-EP-FILTER/endpoint_groups + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-EP-FILTER/1.0/rel/endpoint_groups`` + +Request: + +:: + + { + "endpoint_group": { + "description": "endpoint group description", + "filters": { + "interface": "admin", + "service_id": "1b501a" + } + "name": "endpoint group name", + } + } + +Response: + +:: + + Status: 201 Created + + { + "endpoint_group": { + "description": "endpoint group description", + "filters": { + "interface": "admin", + "service_id": "1b501a" + }, + "id": "ac4861", + "links": { + "self": "http://localhost:35357/v3/OS-EP-FILTER/endpoint_groups/ac4861" + }, + "name": "endpoint group name" + } + } + +Get Endpoint Group +^^^^^^^^^^^^^^^^^^ + +:: + + GET /OS-EP-FILTER/endpoint_groups/{endpoint_group_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-EP-FILTER/1.0/rel/endpoint_group`` + +Response: + +:: + + Status: 200 OK + + { + "endpoint_group": { + "description": "endpoint group description", + "filters": { + "interface": "admin", + "service_id": "1b501a" + }, + "id": "ac4861", + "links": { + "self": "http://localhost:35357/v3/OS-EP-FILTER/endpoint_groups/ac4861" + }, + "name": "endpoint group name" + } + } + +Check Endpoint Group +^^^^^^^^^^^^^^^^^^^^ + +:: + + HEAD /OS-EP-FILTER/endpoint_groups/{endpoint_group_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-EP-FILTER/1.0/rel/endpoint_group`` + +Response: + +:: + + Status: 200 OK + +Update Endpoint Group +^^^^^^^^^^^^^^^^^^^^^ + +:: + + PATCH /OS-EP-FILTER/endpoint_groups/{endpoint_group_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-EP-FILTER/1.0/rel/endpoint_group`` + +The request block is the same as the one for create endpoint group, +except that only the attributes that are being updated need to be +included. + +Request: + +:: + + { + "endpoint_group": { + "description": "endpoint group description", + "filters": { + "interface": "admin", + "service_id": "1b501a" + }, + "name": "endpoint group name" + } + } + +Response: + +:: + + Status: 200 OK + + { + "endpoint_group": { + "description": "endpoint group description", + "filters": { + "interface": "admin", + "service_id": "1b501a" + }, + "id": "ac4861", + "links": { + "self": "http://localhost:35357/v3/OS-EP-FILTER/endpoint_groups/ac4861" + }, + "name": "endpoint group name" + } + } + +Remove Endpoint Group +^^^^^^^^^^^^^^^^^^^^^ + +:: + + DELETE /OS-EP-FILTER/endpoint_groups/{endpoint_group_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-EP-FILTER/1.0/rel/endpoint_group`` + +Response: + +:: + + Status: 204 No Content + +List All Endpoint Groups +^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /OS-EP-FILTER/endpoint_groups + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-EP-FILTER/1.0/rel/endpoint_groups`` + +Response: + +:: + + Status: 200 OK + + { + "endpoint_groups": [ + { + "endpoint_group": { + "description": "endpoint group description #1", + "filters": { + "interface": "admin", + "service_id": "1b501a" + }, + "id": "ac4861", + "links": { + "self": "http://localhost:35357/v3/OS-EP-FILTER/endpoint_groups/ac4861" + }, + "name": "endpoint group name #1" + } + }, + { + "endpoint_group": { + "description": "endpoint group description #2", + "filters": { + "interface": "admin" + }, + "id": "3de68c", + "links": { + "self": "http://localhost:35357/v3/OS-EP-FILTER/endpoint_groups/3de68c" + }, + "name": "endpoint group name #2" + } + } + ], + "links": { + "self": "https://identity:35357/v3/OS-EP-FILTER/endpoint_groups", + "previous": null, + "next": null + } + } + +List Endpoint Groups Associated with Project +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /OS-EP-FILTER/endpoint_groups/projects/{project_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-EP-FILTER/1.0/rel/project_endpoint_groups`` + +Response: + +:: + + Status: 200 OK + + { + "endpoint_groups": [ + { + "endpoint_group": { + "description": "endpoint group description #1", + "filters": { + "interface": "admin", + "service_id": "1b501a" + }, + "id": "ac4861", + "links": { + "self": "http://localhost:35357/v3/OS-EP-FILTER/endpoint_groups/ac4861" + }, + "name": "endpoint group name #1" + } + } + ], + "links": { + "self": "https://identity:35357/v3/OS-EP-FILTER/endpoint_groups", + "previous": null, + "next": null + } + } + +Project to Endpoint Group Relationship +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Create Endpoint Group to Project Association +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + PUT /OS-EP-FILTER/endpoint_groups/{endpoint_group_id}/projects/{project_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-EP-FILTER/1.0/rel/endpoint_group_project`` + +Response: + +:: + + Status: 204 No Content + +Get Endpoint Group to Project Association +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /OS-EP-FILTER/endpoint_groups/{endpoint_group_id}/projects/{project_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-EP-FILTER/1.0/rel/endpoint_group_project`` + +Response: + +:: + + Status: 200 OK + + { + "project": { + "domain_id": "1789d1", + "enabled": true, + "id": "263fd9", + "links": { + "self": "http://identity:35357/v3/projects/263fd9" + }, + "name": "project name #1", + "description": "project description #1" + } + } + +Check Endpoint Group to Project Association +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + HEAD /OS-EP-FILTER/endpoint_groups/{endpoint_group_id}/projects/{project_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-EP-FILTER/1.0/rel/endpoint_group_project`` + +Response: + +:: + + Status: 200 OK + +Delete Endpoint Group to Project Association +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + DELETE /OS-EP-FILTER/endpoint_groups/{endpoint_group_id}/projects/{project_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-EP-FILTER/1.0/rel/endpoint_group_project`` + +Response: + +:: + + Status: 204 No Content + +List Projects Associated with Endpoint Group +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /OS-EP-FILTER/endpoint_groups/{endpoint_group_id}/projects + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-EP-FILTER/1.0/rel/endpoint_group_projects`` + +Response: + +:: + + Status: 200 OK + + { + "projects": [ + { + "domain_id": "1789d1", + "enabled": true, + "id": "263fd9", + "links": { + "self": "http://identity:35357/v3/projects/263fd9" + }, + "name": "a project name 1", + "description": "a project description 1" + }, + { + "domain_id": "1789d1", + "enabled": true, + "id": "61a1b7", + "links": { + "self": "http://identity:35357/v3/projects/61a1b7" + }, + "name": "a project name 2", + "description": "a project description 2" + } + ], + "links": { + "self": "http://identity:35357/v3/OS-EP-FILTER/endpoint_groups/{endpoint_group_id}/projects", + "previous": null, + "next": null + } + } + +List Service Endpoints Associated with Endpoint Group +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /OS-EP-FILTER/endpoint_groups/{endpoint_group_id}/endpoints + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-EP-FILTER/1.0/rel/endpoint_group_endpoints`` + +Response: + +:: + + Status: 200 OK + + { + "endpoints": [ + { + "enabled": true, + "id": "6fedc0" + "interface": "admin", + "legacy_endpoint_id": "6fedc0", + "links": { + "self": "http://identity:35357/v3/endpoints/6fedc0" + }, + "region": "RegionOne", + "service_id": "1b501a", + "url": "http://localhost:9292" + }, + { + "enabled": true, + "id": "b501aa" + "interface": "internal", + "legacy_endpoint_id": "b501aa", + "links": { + "self": "http://identity:35357/v3/endpoints/b501aa" + }, + "region": "RegionOne", + "service_id": "1b501a", + "url": "http://localhost:9292" + }, + { + "enabled": true, + "id": "b7c573" + "interface": "public", + "legacy_endpoint_id": "b7c573", + "links": { + "self": "http://identity:35357/v3/endpoints/b7c573" + }, + "region": "RegionOne", + "service_id": "1b501a", + "url": "http://localhost:9292" + } + ], + "links": { + "self": "http://identity:35357/v3/OS-EP-FILTER/endpoint_groups/{endpoint_group_id}/endpoints", + "previous": null, + "next": null + } + } + diff --git a/api/identity-api-v3-os-federation-ext.rst b/api/identity-api-v3-os-federation-ext.rst new file mode 100644 index 00000000..cd6a6460 --- /dev/null +++ b/api/identity-api-v3-os-federation-ext.rst @@ -0,0 +1,1400 @@ +OpenStack Identity API v3 OS-FEDERATION Extension +================================================= + +Provide the ability for users to manage Identity Providers (IdPs) and +establish a set of rules to map federation protocol attributes to +Identity API attributes. This extension requires v3.0+ of the Identity +API. + +What's New in Version 1.1 +------------------------- + +These features are considered stable as of September 4th, 2014. + +- Introduced a mechanism to exchange an Identity Token for a SAML + assertion. +- Introduced a mechanism to retrieve Identity Provider Metadata. + +Definitions +----------- + +- *Trusted Identity Provider*: An identity provider set up within the + Identity API that is trusted to provide authenticated user + information. +- *Service Provider*: A system entity that provides services to + principals or other system entities, in this case, the OpenStack + Identity API is the Service Provider. +- *Attribute Mapping*: The user information passed by a federation + protocol for an already authenticated identity are called + ``attributes``. Those ``attributes`` may not align 1:1 with the + Identity API concepts. To help overcome such mismatches, a mapping + can be done either on the sending side (third party identity + provider), on the consuming side (Identity API service), or both. + +What's New in Version 1.1 +------------------------- + +Corresponding to Identity API v3.3 release. These features are +considered stable as of September 4th, 2014. + +- Deprecate list projects and domains in favour of core functionality + available in Identity API v3.3. + +API Resources +------------- + +Identity Providers +~~~~~~~~~~~~~~~~~~ + +:: + + /OS-FEDERATION/identity_providers + +An Identity Provider is a third party service that is trusted by the +Identity API to authenticate identities. + +Optional attributes: + +- ``description`` (string) + +Describes the identity provider. + +If a value is not specified by the client, the service may default this +value to either an empty string or ``null``. + +- ``enabled`` (boolean) + +Indicates whether this identity provider should accept federated +authentication requests. + +If a value is not specified by the client, the service may default this +to either ``true`` or ``false``. + +Protocols +~~~~~~~~~ + +:: + + /OS-FEDERATION/identity_providers/{idp_id}/protocols + +A protocol entry contains information that dictates which mapping rules +to use for a given incoming request. An IdP may have multiple supported +protocols. + +Required attributes: + +- ``mapping_id`` (string) + +Indicates which mapping should be used to process federated +authentication requests. + +Mappings +~~~~~~~~ + +:: + + /OS-FEDERATION/mappings + +A ``mapping`` is a set of rules to map federation protocol attributes to +Identity API objects. An Identity Provider can have a single ``mapping`` +specified per protocol. A mapping is simply a list of ``rules``. The +only Identity API objects that will support mapping are: ``group``. + +Required attributes:: + +- ``rules`` (list of objects) + +Each object contains a rule for mapping attributes to Identity API +concepts. A rule contains a ``remote`` attribute description and the +destination ``local`` attribute. + +- ``local`` (list of objects) + + References a local Identity API resource, such as a ``group`` or + ``user`` to which the remote attributes will be mapped. + + Each object has one of two structures, as follows. + + To map a remote attribute value directly to a local attribute, + identify the local resource type and attribute: + + :: + + { + "user": { + "name": "{0}" + } + } + + Note that at least one rule must have a ``user`` attribute. If the + ``user`` attribute is missing when processing an assertion, the + action returns an HTTP 401 Unauthorized error. + + For attribute type and value mapping, identify the local resource + type, attribute, and value: + + :: + + { + "group": { + "id": "89678b" + } + } + + This assigns authorization attributes, by way of role assignments on + the specified group, to ephemeral users. + +- ``remote`` (list of objects) + + At least one object must be included. + + If more than one object is included, the local attribute is applied + only if all remote attributes match. + + The value identified by ``type`` is always passed through unless a + constraint is specified using either ``any_one_of`` or + ``not_one_of``. + + - ``type`` (string) + + This represents an assertion type keyword. + + - ``any_one_of`` (list of strings) + + This is mutually exclusive with ``not_any_of``. + + The rule is matched only if any of the specified strings appear in + the remote attribute ``type``. + + - ``not_any_of`` (list of strings) + + This is mutually exclusive with ``any_one_of``. + + The rule is not matched if any of the specified strings appear in the + remote attribute ``type``. + + - ``regex`` (boolean) + + If ``true``, then each string will be evaluated as a `regular + expression `__ search + against the remote attribute ``type``. + +Identity Provider API +--------------------- + +Register an Identity Provider +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + PUT /OS-FEDERATION/identity_providers/{idp_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-FEDERATION/1.0/rel/identity_provider`` + +Request: + +:: + + { + "identity_provider": { + "description": "Stores ACME identities.", + "enabled": true + } + } + +Response: + +:: + + Status: 201 Created + + { + "identity_provider": { + "description": "Stores ACME identities", + "enabled": true, + "id": "ACME", + "links": { + "protocols": "http://identity:35357/v3/OS-FEDERATION/identity_providers/ACME/protocols", + "self": "http://identity:35357/v3/OS-FEDERATION/identity_providers/ACME" + } + } + } + +List identity providers +~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + GET /OS-FEDERATION/identity_providers + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-FEDERATION/1.0/rel/identity_providers`` + +Response: + +:: + + Status: 200 OK + + { + "identity_providers": [ + { + "description": "Stores ACME identities", + "enabled": true, + "id": "ACME", + "links": { + "protocols": "http://identity:35357/v3/OS-FEDERATION/identity_providers/ACME/protocols", + "self": "http://identity:35357/v3/OS-FEDERATION/identity_providers/ACME" + } + }, + { + "description": "Stores contractor identities", + "enabled": false, + "id": "ACME-contractors", + "links": { + "protocols": "http://identity:35357/v3/OS-FEDERATION/identity_providers/ACME-contractors/protocols", + "self": "http://identity:35357/v3/OS-FEDERATION/identity_providers/ACME-contractors" + } + } + ], + "links": { + "next": null, + "previous": null, + "self": "http://identity:35357/v3/OS-FEDERATION/identity_providers" + } + } + +Get Identity provider +~~~~~~~~~~~~~~~~~~~~~ + +:: + + GET /OS-FEDERATION/identity_providers/{idp_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-FEDERATION/1.0/rel/identity_provider`` + +Response: + +:: + + Status: 200 OK + + { + "identity_provider": { + "description": "Stores ACME identities", + "enabled": false, + "id": "ACME", + "links": { + "protocols": "http://identity:35357/v3/OS-FEDERATION/identity_providers/ACME/protocols", + "self": "http://identity:35357/v3/OS-FEDERATION/identity_providers/ACME" + } + } + } + +Delete identity provider +~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + DELETE /OS-FEDERATION/identity_providers/{idp_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-FEDERATION/1.0/rel/identity_provider`` + +When an identity provider is deleted, any tokens generated by that +identity provider will be revoked. + +Response: + +:: + + Status: 204 No Content + +Update identity provider +~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + PATCH /OS-FEDERATION/identity_providers/{idp_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-FEDERATION/1.0/rel/identity_provider`` + +Request: + +:: + + { + "identity_provider": { + "enabled": true + } + } + +Response: + +:: + + Status: 200 OK + + { + "identity_provider": { + "description": "Beta dev idp", + "enabled": true, + "id": "ACME", + "links": { + "protocols": "http://identity:35357/v3/OS-FEDERATION/identity_providers/ACME/protocols", + "self": "http://identity:35357/v3/OS-FEDERATION/identity_providers/ACME" + } + } + } + +When an identity provider is disabled, any tokens generated by that +identity provider will be revoked. + +Add a protocol and attribute mapping to an identity provider +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + PUT /OS-FEDERATION/identity_providers/{idp_id}/protocols/{protocol_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-FEDERATION/1.0/rel/identity_provider_protocol`` + +Request: + +:: + + { + "protocol": { + "mapping_id": "xyz234" + } + } + +Response: + +:: + + Status: 201 Created + + { + "protocol": { + "id": "saml2", + "mapping_id": "xyz234", + "links": { + "identity_provider": "http://identity:35357/v3/OS-FEDERATION/identity_providers/ACME", + "self": "http://identity:35357/v3/OS-FEDERATION/identity_providers/ACME/protocols/saml2" + } + } + } + +List all protocol and attribute mappings of an identity provider +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + GET /OS-FEDERATION/identity_providers/{idp_id}/protocols + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-FEDERATION/1.0/rel/identity_provider_protocols`` + +Response: + +:: + + Status: 200 OK + + { + "links": { + "next": null, + "previous": null, + "self": "http://identity:35357/v3/OS-FEDERATION/identity_providers/ACME/protocols" + }, + "protocols": [ + { + "id": "saml2", + "links": { + "identity_provider": "http://identity:35357/v3/OS-FEDERATION/identity_providers/ACME", + "self": "http://identity:35357/v3/OS-FEDERATION/identity_providers/ACME/protocols/saml2" + }, + "mapping_id": "xyz234" + } + ] + } + +Get a protocol and attribute mapping for an identity provider +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + GET /OS-FEDERATION/identity_providers/{idp_id}/protocols/{protocol_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-FEDERATION/1.0/rel/identity_provider_protocol`` + +Response: + +:: + + Status: 200 OK + + { + "protocol": { + "id": "saml2", + "mapping_id": "xyz234", + "links": { + "identity_provider": "http://identity:35357/v3/OS-FEDERATION/identity_providers/ACME", + "self": "http://identity:35357/v3/OS-FEDERATION/identity_providers/ACME/protocols/saml2" + } + } + } + +Update the attribute mapping for an identity provider and protocol +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + PATCH /OS-FEDERATION/identity_providers/{idp_id}/protocols/{protocol_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-FEDERATION/1.0/rel/identity_provider_protocol`` + +Request: + +:: + + { + "protocol": { + "mapping_id": "xyz234" + } + } + +Response: + +:: + + Status: 200 OK + + { + "protocol": { + "id": "saml2", + "mapping_id": "xyz234", + "links": { + "identity_provider": "http://identity:35357/v3/OS-FEDERATION/identity_providers/ACME", + "self": "http://identity:35357/v3/OS-FEDERATION/identity_providers/ACME/protocols/saml2" + } + } + } + +Delete a protocol and attribute mapping from an identity provider +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + DELETE /OS-FEDERATION/identity_providers/{idp_id}/protocols/{protocol_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-FEDERATION/1.0/rel/identity_provider_protocol`` + +Response: + +:: + + Status: 204 No Content + +Mapping API +----------- + +Create a mapping +~~~~~~~~~~~~~~~~ + +:: + + PUT /OS-FEDERATION/mappings/{mapping_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-FEDERATION/1.0/rel/mapping`` + +Request: + +:: + + { + "mapping": { + "rules": [ + { + "local": [ + { + "user": { + "name": "{0}" + } + }, + { + "group": { + "id": "0cd5e9" + } + } + ], + "remote": [ + { + "type": "UserName" + }, + { + "type": "orgPersonType", + "not_any_of": [ + "Contractor", + "Guest" + ] + } + ] + } + ] + } + } + +Response: + +:: + + Status: 201 Created + + { + "mapping": { + "links": { + "self": "http://identity:35357/v3/OS-FEDERATION/mappings/ACME" + }, + "id": "ACME", + "rules": [ + { + "local": [ + { + "user": { + "name": "{0}" + } + }, + { + "group": { + "id": "0cd5e9" + } + } + ], + "remote": [ + { + "type": "UserName" + }, + { + "type": "orgPersonType", + "not_any_of": [ + "Contractor", + "Guest" + ] + } + ] + } + ] + } + } + +Get a mapping +~~~~~~~~~~~~~ + +:: + + GET /OS-FEDERATION/mappings/{mapping_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-FEDERATION/1.0/rel/mapping`` + +Response: + +:: + + Status: 200 OK + + { + "mapping": { + "id": "ACME", + "links": { + "self": "http://identity:35357/v3/OS-FEDERATION/mappings/ACME" + }, + "rules": [ + { + "local": [ + { + "user": { + "name": "{0}" + } + }, + { + "group": { + "id": "0cd5e9" + } + } + ], + "remote": [ + { + "type": "UserName" + }, + { + "type": "orgPersonType", + "not_any_of": [ + "Contractor", + "Guest" + ] + } + ] + } + ] + } + } + +Update a mapping +~~~~~~~~~~~~~~~~ + +:: + + PATCH /OS-FEDERATION/mappings/{mapping_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-FEDERATION/1.0/rel/mapping`` + +Request: + +:: + + { + "mapping": { + "rules": [ + { + "local": [ + { + "user": { + "name": "{0}" + } + }, + { + "group": { + "id": "0cd5e9" + } + } + ], + "remote": [ + { + "type": "UserName" + }, + { + "type": "orgPersonType", + "any_one_of": [ + "Contractor", + "SubContractor" + ] + } + ] + } + ] + } + } + +Response: + +:: + + Status: 200 OK + + { + "mapping": { + "id": "ACME", + "links": { + "self": "http://identity:35357/v3/OS-FEDERATION/mappings/ACME" + }, + "rules": [ + { + "local": [ + { + "user": { + "name": "{0}" + } + }, + { + "group": { + "id": "0cd5e9" + } + } + ], + "remote": [ + { + "type": "UserName" + }, + { + "type": "orgPersonType", + "any_one_of": [ + "Contractor", + "SubContractor" + ] + } + ] + } + ] + } + } + +List all mappings +~~~~~~~~~~~~~~~~~ + +:: + + GET /OS-FEDERATION/mappings + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-FEDERATION/1.0/rel/mappings`` + +Response: + +:: + + Status 200 OK + + { + "links": { + "next": null, + "previous": null, + "self": "http://identity:35357/v3/OS-FEDERATION/mappings" + }, + "mappings": [ + { + "id": "ACME", + "links": { + "self": "http://identity:35357/v3/OS-FEDERATION/mappings/ACME" + }, + "rules": [ + { + "local": [ + { + "user": { + "name": "{0}" + } + }, + { + "group": { + "id": "0cd5e9" + } + } + ], + "remote": [ + { + "type": "UserName" + }, + { + "type": "orgPersonType", + "any_one_of": [ + "Contractor", + "SubContractor" + ] + } + ] + } + ] + } + ] + } + +Delete a mapping +~~~~~~~~~~~~~~~~ + +:: + + DELETE /OS-FEDERATION/mappings/{mapping_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-FEDERATION/1.0/rel/mapping`` + +Response: + +:: + + Status: 204 No Content + +Listing projects and domains +---------------------------- + +**Deprecated in v1.1**. This section is deprecated as the functionality +is available in the core Identity API. + +List projects a federated user can access +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + GET /OS-FEDERATION/projects + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-FEDERATION/1.0/rel/projects`` + +**Deprecated in v1.1**. Use core ``GET /auth/projects``. This call has +the same response format. + +Returns a collection of projects to which the federated user has +authorization to access. To access this resource, an unscoped token is +used, the user can then select a project and request a scoped token. +Note that only enabled projects will be returned. + +Response: + +:: + + Status: 200 OK + + { + "projects": [ + { + "domain_id": "37ef61", + "enabled": true, + "id": "12d706", + "links": { + "self": "http://identity:35357/v3/projects/12d706" + }, + "name": "a project name" + }, + { + "domain_id": "37ef61", + "enabled": true, + "id": "9ca0eb", + "links": { + "self": "http://identity:35357/v3/projects/9ca0eb" + }, + "name": "another project" + } + ], + "links": { + "self": "http://identity:35357/v3/OS-FEDERATION/projects", + "previous": null, + "next": null + } + } + +List domains a federated user can access +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + GET /OS-FEDERATION/domains + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-FEDERATION/1.0/rel/domains`` + +**Deprecated in v1.1**. Use core ``GET /auth/domains``. This call has +the same response format. + +Returns a collection of domains to which the federated user has +authorization to access. To access this resource, an unscoped token is +used, the user can then select a domain and request a scoped token. Note +that only enabled domains will be returned. + +Response: + +:: + + Status: 200 OK + + { + "domains": [ + { + "description": "desc of domain", + "enabled": true, + "id": "37ef61", + "links": { + "self": "http://identity:35357/v3/domains/37ef61" + }, + "name": "my domain" + } + ], + "links": { + "self": "http://identity:35357/v3/OS-FEDERATION/domains", + "previous": null, + "next": null + } + } + +Example Mapping Rules +--------------------- + +Map identities to their own groups +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is an example of *Attribute type and value mappings*, where an +attribute type and value are mapped into an Identity API property and +value. + +:: + + { + "rules": [ + { + "local": [ + { + "user": { + "name": "{0}" + } + } + ], + "remote": [ + { + "type": "UserName" + } + ] + }, + { + "local": [ + { + "group": { + "id": "0cd5e9" + } + } + ], + "remote": [ + { + "type": "orgPersonType", + "not_any_of": [ + "Contractor", + "SubContractor" + ] + } + ] + }, + { + "local": [ + { + "group": { + "id": "85a868" + } + } + ], + "remote": [ + { + "type": "orgPersonType", + "any_one_of": [ + "Contractor", + "SubContractor" + ] + } + ] + } + ] + } + +Find specific users, set them to admin group +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is an example that is similar to the previous, but displays how +multiple ``remote`` properties can be used to narrow down on a property. + +:: + + { + "rules": [ + { + "local": [ + { + "user": { + "name": "{0}" + } + }, + { + "group": { + "id": "85a868" + } + } + ], + "remote": [ + { + "type": "UserName" + }, + { + "type": "orgPersonType", + "any_one_of": [ + "Employee" + ] + }, + { + "type": "sn", + "any_one_of": [ + "Young" + ] + } + ] + } + ] + } + +Authenticating +-------------- + +Request an unscoped OS-FEDERATION token +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + GET/POST /OS-FEDERATION/identity_providers/{identity_provider}/protocols/{protocol}/auth + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-FEDERATION/1.0/rel/identity_provider_protocol_auth`` + +A federated user may request an unscoped token, which can be used to get +a scoped token. + +Due to the fact that this part of authentication is strictly connected +with the SAML2 authentication workflow, a client should not send any +data, as the content may be lost when a client is being redirected +between Service Provider and Identity Provider. Both HTTP methods - GET +and POST should be allowed as Web Single Sign-On (WebSSO) and Enhanced +Client Proxy (ECP) mechanisms have different authentication workflows +and use different HTTP methods while accessing protected endpoints. + +The returned token will contain information about the groups to which +the federated user belongs. + +Example Identity API token response: `Various OpenStack token +responses `__ + +Example of an OS-FEDERATION token: + +:: + + { + "token": { + "methods": [ + "saml2" + ], + "user": { + "id": "username%40example.com", + "name": "username@example.com", + "OS-FEDERATION": { + "identity_provider": "ACME", + "protocol": "SAML", + "groups": [ + {"id": "abc123"}, + {"id": "bcd234"} + ] + } + } + } + } + +Request a scoped OS-FEDERATION token +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + POST /auth/tokens + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/auth_tokens`` + +A federated user may request a scoped token, by using the unscoped +token. A project or domain may be specified by either id or name. An id +is sufficient to uniquely identify a project or domain. + +Request Parameters: + +To authenticate with the OS-FEDERATION extension, ``saml2`` must be +specified as an authentication method, and the unscoped token specified +in the id field. + +Example request: + +:: + + { + "auth": { + "identity": { + "methods": [ + "saml2" + ], + "saml2": { + "id": "--federated-token-id--" + } + } + }, + "scope": { + "project": { + "id": "263fd9" + } + } + } + +Similarly to the returned unscoped token, the returned scoped token will +have an ``OS-FEDERATION`` section added to the ``user`` portion of the +token. + +Example of an OS-FEDERATION token: + +:: + + { + "token": { + "methods": [ + "saml2" + ], + "roles": [ + { + "id": "36a8989f52b24872a7f0c59828ab2a26", + "name": "admin" + } + ], + "expires_at": "2014-08-06T13:43:43.367202Z", + "project": { + "domain": { + "id": "1789d1", + "links": { + "self": "http://identity:35357/v3/domains/1789d1" + }, + "name": "example.com" + }, + "id": "263fd9", + "links": { + "self": "http://identity:35357/v3/projects/263fd9" + }, + "name": "project-x" + }, + "catalog": [ + { + "endpoints": [ + { + "id": "39dc322ce86c4111b4f06c2eeae0841b", + "interface": "public", + "region": "RegionOne", + "url": "http://localhost:5000" + }, + { + "id": "ec642f27474842e78bf059f6c48f4e99", + "interface": "internal", + "region": "RegionOne", + "url": "http://localhost:5000" + }, + { + "id": "c609fc430175452290b62a4242e8a7e8", + "interface": "admin", + "region": "RegionOne", + "url": "http://localhost:35357" + } + ], + "id": "266c2aa381ea46df81bb05ddb02bd14a", + "name": "keystone", + "type": "identity" + } + ], + "user": { + "id": "username%40example.com", + "name": "username@example.com", + "OS-FEDERATION": { + "identity_provider": "ACME", + "protocol": "SAML", + "groups": [ + {"id": "abc123"}, + {"id": "bcd234"} + ] + } + }, + "issued_at": "2014-08-06T12:43:43.367288Z" + } + } + +Generating Assertions +--------------------- + +*New in version 1.1* + +Generate a SAML assertion +~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + POST /auth/OS-FEDERATION/saml2 + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-FEDERATION/1.0/rel/saml2`` + +A user may generate a SAML assertion document based on the scoped token +that is used in the request. + +Request Parameters: + +To generate a SAML assertion, a user must provides a scoped token ID and +region ID in the request body. + +Example request: + +:: + + { + "auth": { + "identity": { + "methods": [ + "token" + ], + "token": { + "id": "--token_id--" + } + }, + "scope": { + "region": { + "id": "--region_id--" + } + } + } + } + +The response will be a full SAML assertion. Note that for readability +the certificate has been truncated. + +Response: + +:: + + Headers: + Content-Type: text/xml + + + + + https://www.acme.com + + + + + + + https://www.acme.com + + + + + + + + + + + + + + vzR9Hfp8d16576tEDeq/zhpmLoo= + + + + + AzID5hhJeJlG2llUDvZswNUrlrPtR7S37QYH2W+Un1n8c6kTC + Xr/lihEKPcA2PZt86eBntFBVDWTRlh/W3yUgGOqQBJMFOVbhK + M/CbLHbBUVT5TcxIqvsNvIFdjIGNkf1W0SBqRKZOJ6tzxCcLo + 9dXqAyAUkqDpX5+AyltwrdCPNmncUM4dtRPjI05CL1rRaGeyX + 3kkqOL8p0vjm0fazU5tCAJLbYuYgU1LivPSahWNcpvRSlCI4e + Pn2oiVDyrcc4et12inPMTc2lGIWWWWJyHOPSiXRSkEAIwQVjf + Qm5cpli44Pv8FCrdGWpEE0yXsPBvDkM9jIzwCYGG2fKaLBag== + + + + + MIIEATCCAumgAwIBAgIBBTANBgkqhkiG9w0BAQ0FADCBgzELM + + + + + + + saml01@acme.com + + + + + + + + https://saml.acme.com + + + + + urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified + + + + + + 060D00000000SHZ + + + + 00DD0000000F7L5 + + + + + http://www.acme.com/security/saml/saml20-gen.jsp + + + + + + +For more information about how a SAML assertion is structured, refer to +the `specification `__. + +Retrieve Metadata properties +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + GET /OS-FEDERATION/saml2/metadata + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-FEDERATION/1.0/rel/metadata`` + +A user may retrieve Metadata about an Identity Service acting as an +Identity Provider. + +The response will be a full document with Metadata properties. Note that +for readability, this example certificate has been truncated. + +Response: + +:: + + Headers: + Content-Type: text/xml + + + + + + + + MIIDpTCCAo0CAREwDQYJKoZIhvcNAQEFBQAwgZ + + + + + + openstack + openstack + openstack + + + openstack + first + lastname + admin@example.com + 555-555-5555 + + + +For more information about how a SAML assertion is structured, refer to +the `specification `__. diff --git a/api/identity-api-v3-os-inherit-ext.rst b/api/identity-api-v3-os-inherit-ext.rst new file mode 100644 index 00000000..084ddfa3 --- /dev/null +++ b/api/identity-api-v3-os-inherit-ext.rst @@ -0,0 +1,344 @@ +OpenStack Identity API v3 OS-INHERIT Extension +============================================== + +Provide an ability for projects to inherit roles from their owning +domain. This extension requires v3.1 of the Identity API. + +API +--- + +The following additional APIs are supported by this extension: + +Assign role to user on projects owned by a domain +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + PUT /OS-INHERIT/domains/{domain_id}/users/{user_id}/roles/{role_id}/inherited_to_projects + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-INHERIT/1.0/rel/domain_user_role_inherited_to_projects`` + +The inherited role is only applied to the owned projects (both existing +and future projects), and will not appear as a role in a domain scoped +token. + +Response: + +:: + + Status: 204 No Content + +Assign role to group on projects owned by a domain +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + PUT /OS-INHERIT/domains/{domain_id}/groups/{group_id}/roles/{role_id}/inherited_to_projects + +Relationship: +``http://docs.openstack.org/identity/rel/v3/ext/OS-INHERIT/1.0/domain_group_role_inherited_to_projects`` + +The inherited role is only applied to the owned projects (both existing +and future projects), and will not appear as a role in a domain scoped +token. + +Response: + +:: + + Status: 204 No Content + +List user's inherited project roles on a domain +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /OS-INHERIT/domains/{domain_id}/users/{user_id}/roles/inherited_to_projects + +Relationship: +``http://docs.openstack.org/identity/rel/v3/ext/OS-INHERIT/1.0/domain_user_roles_inherited_to_projects`` + +The list only contains those role assignments to the domain that were +specified as being inherited to projects within that domain. + +Response: + +:: + + Status: 200 OK + + { + "roles": [ + { + "id": "--role-id--", + "links": { + "self": "http://identity:35357/v3/roles/--role-id--" + }, + "name": "--role-name--", + }, + { + "id": "--role-id--", + "links": { + "self": "http://identity:35357/v3/roles/--role-id--" + }, + "name": "--role-name--" + } + ], + "links": { + "self": "http://identity:35357/v3/OS-INHERIT/domains/--domain_id--/ + users/--user_id--/roles/inherited_to_projects", + "previous": null, + "next": null + } + } + +List group's inherited project roles on domain +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /OS-INHERIT/domains/{domain_id}/groups/{group_id}/roles/inherited_to_projects + +Relationship: +``'http://docs.openstack.org/identity/rel/v3/ext/OS-INHERIT/1.0/domain_group_roles_inherited_to_projects`` + +The list only contains those role assignments to the domain that were +specified as being inherited to projects within that domain. + +Response: + +:: + + Status: 200 OK + + { + "roles": [ + { + "id": "--role-id--", + "links": { + "self": "http://identity:35357/v3/roles/--role-id--" + }, + "name": "--role-name--", + }, + { + "id": "--role-id--", + "links": { + "self": "http://identity:35357/v3/roles/--role-id--" + }, + "name": "--role-name--" + } + ], + "links": { + "self": "http://identity:35357/v3/OS-INHERIT/domains/--domain_id--/ + groups/--group_id--/roles/inherited_to_projects", + "previous": null, + "next": null + } + } + +Check if user has an inherited project role on domain +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + HEAD /OS-INHERIT/domains/{domain_id}/users/{user_id}/roles/{role_id}/inherited_to_projects + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-INHERIT/1.0/rel/domain_user_role_inherited_to_projects`` + +Response: + +:: + + Status: 204 No Content + +Check if group has an inherited project role on domain +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + HEAD /OS-INHERIT/domains/{domain_id}/groups/{group_id}/roles/{role_id}/inherited_to_projects + +Relationship: +``http://docs.openstack.org/identity/rel/v3/ext/OS-INHERIT/1.0/domain_group_role_inherited_to_projects`` + +Response: + +:: + + Status: 204 No Content + +Revoke an inherited project role from user on domain +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + DELETE /OS-INHERIT/domains/{domain_id}/users/{user_id}/roles/{role_id}/inherited_to_projects + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-INHERIT/1.0/rel/domain_user_role_inherited_to_projects`` + +Response: + +:: + + Status: 204 No Content + +Revoke an inherited project role from group on domain +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + DELETE /OS-INHERIT/domains/{domain_id}/groups/{group_id}/roles/{role_id}/inherited_to_projects + +Relationship: +``http://docs.openstack.org/identity/rel/v3/ext/OS-INHERIT/1.0/domain_group_role_inherited_to_projects`` + +Response: + +:: + + Status: 204 No Content + +Modified APIs +------------- + +The following APIs are modified by this extension. + +List effective role assignments +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /role_assignments + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/role_assignments`` + +The scope section in the list response is extended to allow the +representation of role assignments that are inherited to projects. + +Response: + +:: + + Status: 200 OK + + { + "role_assignments": [ + { + "links": { + "assignment": "http://identity:35357/v3/OS-INHERIT/ + domains/--domain-id--/users/--user-id--/ + roles/--role-id--/inherited_to_projects" + }, + "role": { + "id": "--role-id--" + }, + "scope": { + "domain": { + "id": "--domain-id--" + }, + "OS-INHERIT:inherited_to": ["projects"] + }, + "user": { + "id": "--user-id--" + } + }, + { + "group": { + "id": "--group-id--" + }, + "links": { + "assignment": "http://identity:35357/v3/projects/--project-id--/ + groups/--group-id--/roles/--role-id--" + }, + "role": { + "id": "--role-id--" + }, + "scope": { + "project": { + "id": "--project-id--" + } + } + } + ], + "links": { + "self": "http://identity:35357/v3/role_assignments", + "previous": null, + "next": null + } + } + +An additional query filter ``scope.OS-INHERIT:inherited_to`` is +supported to allow for filtering based on role assignments that are +inherited. The only value of ``scope.OS-INHERIT:inherited_to`` that is +currently supported is ``projects``, indicating that this role is +inherited to all projects of the owning domain. + +If the query\_string ``effective`` is specified then the list of +effective assignments at the user, project and domain level allows for +the effects of both group membership as well as inheritance from the +parent domain (for role assignments that were made using OS-INHERIT +assignment APIs). Since, like group membership, the effects of +inheritance have already been allowed for, the role assignment entities +themselves that specify the inheritance will not be returned in the +collection. + +An example response for an API call with the query\_string ``effective`` +specified is given below: + +Response: + +:: + + Status: 200 OK + + { + "role_assignments": [ + { + "links": { + "assignment": "http://identity:35357/v3/OS-INHERIT/ + domains/--domain-id--/users/--user-id--/ + roles/--role-id--/inherited_to_projects" + }, + "role": { + "id": "--role-id--" + }, + "scope": { + "project": { + "id": "--project-id--" + } + }, + "user": { + "id": "--user-id--" + } + }, + { + "links": { + "assignment": "http://identity:35357/v3/projects/--project-id--/ + groups/--group-id--/roles/--role-id--", + "membership": "http://identity:35357/v3/groups/--group-id--/ + users/--user-id--" + }, + "role": { + "id": "--role-id--" + }, + "scope": { + "project": { + "id": "--project-id--" + } + }, + "user": { + "id": "--user-id--" + } + } + ], + "links": { + "self": "http://identity:35357/v3/role_assignments?effective", + "previous": null, + "next": null + } + } + diff --git a/api/identity-api-v3-os-kds-ext.rst b/api/identity-api-v3-os-kds-ext.rst new file mode 100644 index 00000000..70a6b694 --- /dev/null +++ b/api/identity-api-v3-os-kds-ext.rst @@ -0,0 +1,524 @@ +OpenStack Identity API v3 Key Distribution Service Extension +============================================================ + +Key Distribution Server (KDS) serves as a trusted third party that is +responsible for generation and secure distribution of signing and +encryption keys to communicating parties. These shared keys allow +messages to be exchanged between communicating parties with message +authentication, integrity and confidentiality. KDS is an integral part +of the implementation of RPC message security. + +To establish a trusted relationship between a communicating party and +KDS, a long term shared key needs to be assigned to the party by a +properly authorized user, such as a cloud administrator. Assigning a key +to a party requires assigning an identity to that party in KDS. An +identity is comprised of a unique party name and the long term shared +key that it is associated with. This party name is used to identify a +party when it communicates with KDS or another party. + +KDS is designed to enable secure messages to be exchanged between two +individual parties as well as between one individual party and a group +party. When a party wants to obtain keys to be used for communication +with another party, it makes an authenticated request to KDS for a +ticket. KDS returns a ticket to the requesting party that is encrypted +with the long term shared key that is associated with that party. This +encryption ensures that the ticket can only be decrypted by one who +possesses the long term key, which should only be the associated party +and KDS itself. + +A ticket that has been issued by KDS contains a copy of the shared +encryption and signing keys. These keys are for the source party, which +is the party that requested the ticket. The ticket also contains a +payload that is intended for the destination party, which is the party +that the source party wants to communicate with. This payload contains +the information that is needed for the destination party to be able to +derive the shared encryption and signing keys. When the destination +party is an individual, the payload is encrypted with the long term +shared key that is associated with the destination party. When the +destination party is a group, the payload is encrypted with a shared +group key that KDS makes available to all members of the group. This +encryption allows the destination party to trust that the information in +the payload was supplied by KDS. When the source party is ready to +communicate with the destination party, it sends this encrypted payload +to the destination party along with whatever data it has protected with +the shared signing and encryption keys. The destination party can then +decrypt the payload and derive the shared encryption and signing keys +using the information in the payload. This results in both parties +having a copy of the shared signing and encryption keys that are trusted +as being issued by KDS. These shared keys can then be used by the +destination party to authenticate and decrypt the data sent by the +source party. + +When a source party needs to send secure messages to multiple +recipients, an authorized user can define a group for those recipients +in KDS. Membership in a group is determined by comparing a party name +with the group name. If the name of a party matches ``.*``, +it is considered to be a member. For example, a party named +``scheduler.host.example.com`` would be considered a member of a group +named ``scheduler``. This matches up with the way that message queues +are named within OpenStack. + +When a source party requests a ticket where the destination party is a +group, KDS generates a short-lived group key and assigns it to the +group. This group key is used to encrypt the payload in the ticket, +which contains the information that the destination party uses to derive +the shared signing and encryption keys. When an individual destination +party needs to decrypt the payload that it receives from the source +party as a part of a group message, it makes an authenticated request to +KDS to obtain the short-lived group key. If the requester is a member of +the target group, KDS provides the short-lived group key encrypted with +the long term shared key associated with the individual destination +party. The group key can then be decrypted by the individual destination +party, allowing it to decrypt the payload and derive the shared signing +and encryption keys that can be used to authenticate and decrypt the +data sent by the source party. + +When keys are obtained to send a message to a group, it is important to +note that all members of the group and the sender share the signing and +encryption keys. This makes it impossible for an individual destination +party to determine if a message was truly sent by the source party or +another destination party who is a member of the group. The only +assurance that a destination party has is that a message was sent by a +party who has possession of the shared signing and encryption keys. This +requires that all parties within a group trust each other to not +impersonate the source party. + +The signing and encryption keys that are shared between communicating +parties are short-lived. The lifetime of these keys is defined by an +validity period that is set by KDS when it issues the ticket. A +suggested reasonable default validity period is 15 minutes, though it is +left up to the implementation to determine the appropriate validity +period. Once the validity period for the keys expires, a party should +refuse to use those keys anymore to prevent using keys that may have +been compromised. This requires the source party to request a new ticket +from KDS to get a new set of keys. If desired, an implementation could +choose to implement a grace period to account for clock skew between +parties. This grace period would allow a destination party to accept +messages that use recently expired keys. If a grace period is used, it +is recommended that the duration be kept small, such as 5 minutes or +less. + +The principal advantage of using a key server compared to a pure public +key based system is that the encryption and signing key exchange can be +regulated by the key server. Since the key server is actively involved +in distributing keys to the communicating parties, it has the ability to +apply access control and deny communication between arbitrary peers in +the system when keys are requested. This allows for centralized access +control, prevents unauthorized communication and avoids the need to +perform post-authentication access control and policy look-ups on the +receiving side. + +API Considerations +------------------ + +The Key Distribution Server (KDS) requires that all ticket requests are +authenticated and data is encrypted where appropriate. + +All timestamp values used in the API must be specified as a UTC ISO 8601 +extended format date/time string that includes microseconds. An example +of a properly formatted timestamp is ``2012-03-26T10:01:01.720000``. + +The default algorithms for message authentication and encryption are +respectively HMAC-SHA-256 and AES-128-CBC. Therefore the default block +size is 128bit. + +The source party that obtains a ticket is responsible for sending the +encrypted payload ``esek`` to the destination party. The source and +destination strings used when requesting the ticket also need to be sent +to the destination party to allow it to derive the shared signing end +encryption keys. Transferring this data to the destination party is +handled outside of the API described in this document, as it's expected +to be performed by the messaging implementation. + +The key derivation used to generate the shared signing and encryption +keys uses the Hashed Message Authentication Code (HMAC)-based key +derivation function (HKDF) standard as described in RFC 5869. The +destination party needs to use the HKDF ``expand`` function using the +information that it receives from the source party in order to complete +derivation of the shared signing and encryption keys. The inputs to the +HKDF ``expand`` function are as follows: + +:: + + HKDF-Expand(esek.key, info, 256) + +The ``info`` input for the HKDF ``expand`` function is a string that +concatenates the source, destination, and ``esek.timestamp`` strings +using a ``,`` separator between each element. An example of a valid +``info`` string where ``scheduler.host.example.com`` is the source, +``compute.host.example.com`` is the destination, and +``2012-03-26T10:01:01.720000`` is the ``esek.timestamp`` is as follows: + +:: + + scheduler.host.example.com,compute.host.example.com,2012-03-26T10:01:01.720000 + +The output of the HKDF expand function is an array of bytes of 256 bit +length. The first half is used as the signing key, and the second half +is used as the encryption key. + +The requests to create and delete long term keys should be restricted +such that only a properly authorized user, such as a cloud administrator +is allowed to successfully perform the operations. The authentication +and authorization for these requests is left up to the implementation, +though it expected that one would leverage the Identity API for these +purposes. + +Resources and Operations +------------------------ + +Create Key +^^^^^^^^^^ + +:: + + PUT /v1/keys/{name} + +Create a long term key in the KDS. + +Request +''''''' + +The request resource name is the party associated with the key, and the +body consists of just the key. + +- ``key`` - A base64 encoded 128 bit long cryptographic random key. + + { "key": "TXkgcHJlY2lvdXNzcy4u..." } + +Response +'''''''' + +The response contains a name and generation value. The generation value +will only be changed if a new key is set. If the request sets the key to +the same value that already exists, the existing generation value will +be returned in the response. This makes the request idempotent. + +- ``name`` - The party name associated with the key. +- ``generation`` - A unique integer used to identify the key. + + Status: 201 Created Location: /v1/keys/--key-name-- + + { "name": "--key-name--", "generation": 2 } + +Delete Key +^^^^^^^^^^ + +:: + + DELETE /v1/keys/{name} + +Delete a key from KDS. + +Request +''''''' + +The request body is empty. + +Response +'''''''' + +:: + + Status: 204 No Content + +Generate Ticket +^^^^^^^^^^^^^^^ + +:: + + POST /v1/tickets + +A ticket is generated to facilitate messaging between a ``source`` and a +``destination``. + +Request +''''''' + +A generate ticket request comprises metadata supplied as a base64 +encoded JSON object and a signature. + +:: + + { + "metadata": "Zhn8yhasf8hihkf...", + "signature": "c2lnbmF0dXJl..." + } + +Metadata: + +A base64 encoded JSON object containing the following key/value pairs: + +- ``source`` - The identity requesting a ticket. +- ``destination`` - The target for which the ticket will be valid. +- ``timestamp`` - Current timestamp from the requester. +- ``nonce`` - Random single use data. + +A timestamp and a nonce are necessary to avoid replay attacks. + +:: + + { + "source": "scheduler.host.example.com", + "destination": "compute.host.example.com", + "timestamp": "2012-03-26T10:01:01.720000", + "nonce": 1234567890 + } + +Signature: + +A base64 encoded HMAC Signature over the base64 encoded request metadata +object. + +:: + + Base64encode(HMAC(SigningKey, RequestMetadata)) + +The key used for the signature is the requester's long term key. The KDS +should verify the signature upon receipt of the request. This requires +that the KDS access the ``source`` from the request metadata in order to +lookup the associated long term key that can be used to verify the +signature. The KDS should not access any other data contained in the +request metadata before verifying the signature. Failure to verify the +signature leaves the KDS open to issuing a ticket to a party that is +impersonating the source. + +Response +'''''''' + +The response always returns a triplet of metadata, encrypted ticket and +signature. + +:: + + Status: 200 OK + + { + "metadata": "Zhn8yhasf8hihkf...", + "ticket": "ZW5jcnlwdGVkIHRpY2tldA==", + "signature": "c2lnbmF0dXJl..." + } + +Metadata: + +A base64 encoded JSON object containing the following key/value pairs: + +- ``source`` - The identity of the requester. +- ``destination`` - The target for which the ticket is valid. +- ``expiration`` - Timestamp of when the ticket expires. + + { "source": "scheduler.host.example.com", "destination": + "compute.host.example.com", "expiration": + "2012-03-26T11:01:01.720000" } + +Ticket: + +The ticket is encrypted with the source's long term key and contains a +base64 encoded JSON object containing the following key/value pairs: + +- ``skey`` - The newly generated base64 encoded message signing key. +- ``ekey`` - The newly generated base64 encoded message encryption key. +- ``esek`` - Encrypted signing and encryption key pair for the + receiver. + + { "skey": "ZjhkuYZH8y87rzhgi7..." "ekey": "Fk8yksa8z8zKtakc8s..." + "esek": "KBo8fajfo8ysad5hq2..." } + +The ``esek`` is encrypted with the destination's long term key and +contains a base64 encoded JSON object containing the following key/value +pairs: + +- ``key`` - The base64 encoded random key used to derive the signing + and encryption keys. +- ``timestamp`` - Timestamp of when the key was created. +- ``ttl`` - An integer containing the validity length of the key in + seconds. + + { "key": "Afa8sad2hgsd7asv7ad..." "timestamp": + "2012-03-26T10:01:01.720000" "ttl": 28800 } + +The ``key`` and ``timestamp`` are used as inputs to the HKDF ``expand`` +function to derive the signing and encryption keys as described in the +``API Considerations`` section of this document. + +The ``timestamp`` plus ``ttl`` should be equivalent to the +``expiration`` timestamp contained in the response metadata. + +Signature: + +A base64 encoded HMAC signature over the concatenation of the base64 +encoded response metadata object and base64 encoded ticket object. + +:: + + Base64encode(HMAC(SigningKey, ResponseMetadata + Ticket)) + +The key used for the signature is the requester's long term key. The +requester should verify the signature upon receipt of the response +before accessing any data contained in the response metadata or the +ticket. Failure to verify the signature leaves the requester open to +using metadata that was not actually issued by the KDS. + +Create Group +^^^^^^^^^^^^ + +:: + + PUT /v1/groups/{name} + +Create a group in the KDS. + +Membership in groups is based on the party name. For example, a group +named ``scheduler`` will implicitly include any party name starting with +``scheduler.`` as a member (e.g. scheduler.host.example.com). + +Request +''''''' + +The request body is empty. + +Response +'''''''' + +The response returns the group name from the request. + +:: + + Status: 201 Created + Location: /v1/groups/--group-name-- + + { + "name": "--group-name--" + } + +Delete Group +^^^^^^^^^^^^ + +:: + + DELETE /v1/groups/{name} + +Delete a group from the KDS. + +Request +''''''' + +The request body is empty. + +Response +'''''''' + +:: + + Status: 204 No Content + +Retrieve Group Key +^^^^^^^^^^^^^^^^^^ + +:: + + POST /v1/groups + +When a ticket is requested where the destination is a group, a group key +is generated that is valid for a predetermined amount of time. Any +member of the group can retrieve the key as long as it is still valid. +Group keys are necessary to verify signatures and decrypt messages that +have a group name as the target. + +Request +''''''' + +A group key retrieval request is identical to a generate ticket request +except the destination is a group name instead of an individual party +name. + +Response +'''''''' + +The response always returns a triplet of metadata, encrypted group key +and signature. + +:: + + Status: 200 OK + + { + "metadata": "Zhn8yhasf8hihkf...", + "group_key": "ZW5jcnlwdGVkIGdyb3VwIGtleQ==", + "signature": "c2lnbmF0dXJl" + } + +Metadata: + +A base64 encoded JSON object containing the following key/value pairs: + +- ``source`` - The identity of the requester. +- ``destination`` - The target for which the ticket is valid. +- ``expiration`` - Timestamp of when the ticket expires. + + { "source": "api.host.example.com", "destination": "scheduler", + "expiration": "2012-03-26T11:01:01.720000" } + +Group key: + +The group key is encrypted with the requester's long term key. + +Signature: + +A base64 encoded HMAC signature over the concatenation of the base64 +encoded response metadata object and the group key. + +:: + + Base64encode(HMAC(SigningKey, ResponseMetadata + GroupKey)) + +The key used for the signature is the requester's long term key. The +requester should verify the signature upon receipt of the response +before accessing any data contained in the response metadata or the +group key. Failure to verify the signature leaves the requester open to +using data that was not actually issued by the KDS. + +HTTP Status Codes +~~~~~~~~~~~~~~~~~ + +KDS uses the following HTTP status codes to communicate specific success +and failure conditions to the client. + +200 OK +^^^^^^ + +This status code is returned in response to a successful ``POST`` +request to generate a ticket or a retrieve a group key. + +201 Created +^^^^^^^^^^^ + +This status code is returned in response to a successful ``PUT`` request +to create a group or long term key. + +204 No Content +^^^^^^^^^^^^^^ + +This status code is returned in response to a successful ``DELETE`` +request to delete a group or long term key. No content body is returned. + +401 Unauthorized +^^^^^^^^^^^^^^^^ + +This status code is returned when either authentication has not been +performed, or authentication fails. + +403 Forbidden +^^^^^^^^^^^^^ + +This status code is returned when the requester field does not match +either the sender or the receiver fields, or if the body of the request +does not result in the supplied signature. + +404 Not Found +^^^^^^^^^^^^^ + +This status code is returned in response to a failed ``DELETE`` request +when a referenced entity cannot be found. It is also returned when a +``POST`` request is made where the destination party specified in the +request does not exist. diff --git a/api/identity-api-v3-os-oauth1-ext.rst b/api/identity-api-v3-os-oauth1-ext.rst new file mode 100644 index 00000000..0131056d --- /dev/null +++ b/api/identity-api-v3-os-oauth1-ext.rst @@ -0,0 +1,535 @@ +OpenStack Identity API v3 OS-OAUTH1 Extension +============================================= + +Provide the ability for identity users to delegate roles to third party +consumers via the `OAuth 1.0a +specification `__. This extension requires +v3.0+ of the Identity API. An OAuth-derived token will provide a means +of acting on behalf of the authorizing user. + +Definitions +----------- + +- *User:* An Identity API service user, the entity whose role(s) will + be delegated, and the entity that authorizes Request Tokens. +- *Request Token:* A token used by the Consumer to obtain authorization + from the User, and exchanged with an OAuth Verifier for an Access + Token. +- *Access Token:* A token used by the Consumer to request new Identity + API tokens on behalf of the authorizing User, instead of using the + User’s credentials. +- *Token Key:* A key used by the token to identify itself. Both Request + Tokens and Access Tokens have Token Keys. For OpenStack purposes, the + Token Key is the Token ID. +- *Token Secret:* A secret used by the Consumer to establish ownership + of a given Token. Both Request Tokens and Access Tokens have Token + Secrets. +- *OAuth Verifier:* A string that must be provided with the + corresponding Request Token in exchange for an Access Token. + +Delegated Authentication Flow +----------------------------- + +Delegated Authentication via OAuth is done in five steps: + +1. An Identity API service User `creates a + Consumer <#create-consumer-post-os-oauth1consumers>`__. +2. The Consumer `obtains an unauthorized Request + Token <#create-request-token-post-os-oauth1request_token>`__. +3. The User `authorizes the Request + Token <#authorize-request-token-put-os-oauth1authorizerequest_token_id>`__. +4. The Consumer `exchanges the Request Token for an Access + Token <#create-access-token-post-os-oauth1access_token>`__. +5. The Consumer `uses the Access Token to request an Identity API + service Token <#request-an-identity-api-token-post-authtokens>`__. + +API Resources +------------- + +Consumers +~~~~~~~~~ + +:: + + /OS-OAUTH1/consumers + +A Consumer is an application that uses OAuth to access a protected +resource. + +Optional attributes: + +- ``description`` (string) + +Immutable attributes provided by the Identity service: + +- ``secret`` (string) + +A consumer's ``secret`` is only returned once, during consumer creation. + +The Consumer is given its key and secret, out-of-band. For OpenStack, +the ID of the Consumer is the Key. + +Consumers API +------------- + +Create Consumer +~~~~~~~~~~~~~~~ + +:: + + POST /OS-OAUTH1/consumers + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-OAUTH1/1.0/rel/consumers`` + +Request: + +:: + + { + "consumer": { + "description": "My consumer" + } + } + +Response: + +The ``secret`` is only returned once, during consumer creation. + +:: + + Status: 201 Created + + { + "consumer": { + "secret": "4c7832", + "description": "My consumer", + "id": "7fea2d", + "links": { + "self": "http://identity:35357/v3/OS-OAUTH1/consumers/7fea2d" + } + } + } + +List Consumers +~~~~~~~~~~~~~~ + +:: + + GET /OS-OAUTH1/consumers + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-OAUTH1/1.0/rel/consumers`` + +Response: + +:: + + Status: 200 OK + + { + "consumers": [ + { + "id": "0c2a74", + "links": { + "self": "http://identity:35357/v3/OS-OAUTH1/consumers/0c2a74" + } + }, + { + "description": "My consumer", + "id": "7fea2d", + "links": { + "self": "http://identity:35357/v3/OS-OAUTH1/consumers/7fea2d" + } + } + ], + "links": { + "next": null, + "previous": null, + "self": "http://identity:35357/v3/OS-OAUTH1/consumers" + } + } + +Get Consumer +~~~~~~~~~~~~ + +:: + + GET /OS-OAUTH1/consumers/{consumer_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-OAUTH1/1.0/rel/consumer`` + +Response: + +:: + + Status: 200 OK + + { + "consumer": { + "id": "7fea2d", + "description": "My consumer", + "links": { + "self": "http://identity:35357/v3/OS-OAUTH1/consumers/7fea2d" + } + } + } + +Delete Consumer +~~~~~~~~~~~~~~~ + +:: + + DELETE /OS-OAUTH1/consumers/{consumer_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-OAUTH1/1.0/rel/consumer`` + +When a Consumer is deleted, any Request Tokens, Access Tokens, or +Identity API Tokens will also be deleted. + +Response: + +:: + + Status: 204 No Content + +Update Consumer +~~~~~~~~~~~~~~~ + +:: + + PATCH /OS-OAUTH1/consumers/{consumer_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-OAUTH1/1.0/rel/consumer`` + +Only a Consumer's ``description`` is mutable. Attempting to PATCH an +immutable attribute should result in a HTTP 400 Bad Request. + +Request: + +:: + + { + "consumer": { + "description": "My new consumer" + } + } + +Response: + +:: + + Status: 200 OK + + { + "consumer": { + "description": "My new consumer", + "id": "7fea2d", + "links": { + "self": "http://identity:35357/v3/OS-OAUTH1/consumers/7fea2d" + } + } + } + +Delegated Auth APIs +------------------- + +Create Request Token +~~~~~~~~~~~~~~~~~~~~ + +:: + + POST /OS-OAUTH1/request_token + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-OAUTH1/1.0/rel/request_tokens`` + +A Consumer uses the Consumer Key and Secret to obtain a Request Token. +The Request Token is used to initiate User authorization. The Request +Token, once authorized, can be exchanged along with the OAuth Verifier +for an Access Token. Note that there is one extra parameter, +``requested_project_id``. ``requested_project_id`` contains the ID of +the project upon which the Consumer would like authorization. The +Identity service may include an ``oauth_expires_at`` attribute in the +response. If no such attribute is included, or is null, then the token +may last indefinitely. + +The authorizing User receives the Request Token Key from the Consumer +out-of-band. + +Supported signature methods: ``HMAC-SHA1`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Request Parameters: + +- All required OAuth parameters must be provided. + +See: http://oauth.net/core/1.0a/#auth_step1 + +Additional Request Parameters: + +- ``requested_project_id``: IDs of requested project + +- Example: ``requested_project_id=b9fca3`` + +Response: + +``oauth_token=29971f&oauth_token_secret=238eb8&oauth_expires_at=2013-09-11T06:07:51.501805Z`` + +Response Parameters: + +- ``oauth_token``: The Request Token key that the Identity API returns. +- ``oauth_token_secret``: The secret associated with the Request Token. +- ``oauth_expires_at`` (optional): The ISO 8601 date time at which a + Request Token will expire. + +Authorize Request Token +~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + PUT /OS-OAUTH1/authorize/{request_token_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-OAUTH1/1.0/rel/authorize_request_token`` + +To authorize the Request Token, the authorizing user must have access to +the requested project. Upon successful authorization, an OAuth Verifier +code is returned. The Consumer receives the OAuth Verifier from the User +out-of-band. + +Request: + +:: + + { + "roles": [ + { + "id": "a3b29b" + }, + { + "id": "49993e" + } + ] + } + +Response: + +:: + + { + "token": { + "oauth_verifier": "8171" + } + } + +Create Access Token +~~~~~~~~~~~~~~~~~~~ + +:: + + POST /OS-OAUTH1/access_token + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-OAUTH1/1.0/rel/access_tokens`` + +After the User authorizes the Request Token, the Consumer exchanges the +authorized Request Token and OAuth Verifier for an Access Token. The +Identity service may include an ``oauth_expires_at`` parameter in the +response. If no such parameter is included, then the token lasts +indefinitely. + +Supported signature methods: ``HMAC-SHA1`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Request Parameters: + +- All required OAuth parameters must be provided. + +See: http://oauth.net/core/1.0a/#auth_step3 + +Response: + +:: + + oauth_token=accd36&oauth_token_secret=aa47da&oauth_expires_at=2013-09-11T06:07:51.501805Z + +Response Parameters: + +- ``oauth_token``: The Access Token key that the Identity API returns. +- ``oauth_token_secret``: The secret associated with the Access Token. +- ``oauth_expires_at`` (optional): The ISO 8601 date time when an + Access Token expires. + +Request an Identity API Token +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + POST /auth/tokens + +Relationship: ``http://docs.openstack.org/identity/rel/v3/auth_tokens`` + +The Consumer can now request valid Identity API service tokens +representing the authorizing User's delegated authorization and identity +(impersonation). The generated token's roles and scope will match that +which the Consumer initially requested. + +Supported signature methods: ``HMAC-SHA1`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Request Parameters: + +- All required OAuth parameters must be provided. + +See: http://oauth.net/core/1.0a/#anchor12 + +To authenticate with the OS-OAUTH1 extension, ``oauth1`` must be +specified as an authentication method. Example request: + +:: + + { + "auth": { + "identity": { + "methods": [ + "oauth1" + ], + "oauth1": {} + } + } + } + +The returned token is scoped to the requested project and with the +delegated roles. In addition to the standard token response, as seen in +the link below, the token has an OAuth-specific object. + +Example OpenStack token response: `Various OpenStack token +responses `__ + +Example OAuth-specific object in a token: + +:: + + "OS-OAUTH1": { + "consumer_id": "7fea2d", + "access_token_id": "cce0b8be7" + } + +User Access Token APIs +---------------------- + +List authorized access tokens +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + GET /users/{user_id}/OS-OAUTH1/access_tokens + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-OAUTH1/1.0/rel/user_access_tokens`` + +Response: + +:: + + { + "access_tokens": [ + { + "consumer_id": "7fea2d", + "id": "6be26a", + "expires_at": "2013-09-11T06:07:51.501805Z", + "links": { + "roles": "http://identity:35357/v3/users/ce9e07/OS-OAUTH1/access_tokens/6be26a/roles" + "self": "http://identity:35357/v3/users/ce9e07/OS-OAUTH1/access_tokens/6be26a" + }, + "project_id": "b9fca3", + "authorizing_user_id": "ce9e07" + } + ], + "links": { + "next": null, + "previous": null, + "self": "http://identity:35357/v3/users/ce9e07/OS-OAUTH1/access_tokens" + } + } + +Get authorized access token +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + GET /users/{user_id}/OS-OAUTH1/access_tokens/{access_token_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-OAUTH1/1.0/rel/user_access_token`` + +Response: + +:: + + { + "access_token": { + "consumer_id": "7fea2d", + "id": "6be26a", + "expires_at": "2013-09-11T06:07:51.501805Z", + "links": { + "roles": "http://identity:35357/v3/users/ce9e07/OS-OAUTH1/access_tokens/6be26a/roles" + "self": "http://identity:35357/v3/users/ce9e07/OS-OAUTH1/access_tokens/6be26a" + }, + "project_id": "b9fca3", + "authorizing_user_id": "ce9e07" + } + } + +List roles of an access token +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + GET /users/{user_id}/OS-OAUTH1/access_tokens/{access_token_id}/roles + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-OAUTH1/1.0/rel/user_access_token_roles`` + +See ``GET /v3/roles`` for an +`example `__ +of this response format. + +Get a role of an access token +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + GET /users/{user_id}/OS-OAUTH1/access_tokens/{access_token_id}/roles/{role_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-OAUTH1/1.0/rel/user_access_token_role`` + +See ``GET /v3/roles/{role_id}`` for an +`example `__ +of this response format. + +Revoke access token +~~~~~~~~~~~~~~~~~~~ + +:: + + DELETE /users/{user_id}/OS-OAUTH1/access_tokens/{access_token_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-OAUTH1/1.0/rel/user_access_token`` + +A User can revoke an Access Token, preventing the Consumer from +requesting new Identity API service tokens. This also revokes any +Identity API tokens issued to the Consumer using that Access Token. + +Response: + +:: + + Status: 204 No Content + diff --git a/api/identity-api-v3-os-revoke-ext.rst b/api/identity-api-v3-os-revoke-ext.rst new file mode 100644 index 00000000..4bc7c248 --- /dev/null +++ b/api/identity-api-v3-os-revoke-ext.rst @@ -0,0 +1,175 @@ +OpenStack Identity API v3 OS-REVOKE Extension +============================================= + +This extension provides a list of token revocations. Each event +expresses a set of criteria which describes a set of tokens that are no +longer valid. + +This extension requires v3.2+ of the Identity API. + +What's New in v1.1 +------------------ + +- Use of ``expires_at`` has been deprecated in favor of using + ``audit_id`` and ``audit_chain_id``. + +- Revocation events can use ``audit_id`` to revoke an individual token. + +- Revocation events can use ``audit_chain_id`` to revoke all related + tokens. A related token is defined by the first (non-rescoped) token. + All tokens in the chain will have the same ``audit_chain_id``. + +API Resources +------------- + +Revocation Events +~~~~~~~~~~~~~~~~~ + +Revocation events are objects that contain criteria used to evaluate +token validity. Tokens that match all the criteria of a revocation event +are considered revoked, and should not be accepted as proof of +authorization for the user. + +Revocation events do not have a unique identifier (``id``). + +Required attributes: + +- ``issued_before`` (string, ISO 8601 extended format date time with + microseconds) + +Tokens issued before this time are considered revoked. + +This attribute can be used to determine how long the expiration event is +valid. It can also be used in queries to filter events, so that only a +subset that have occurred since the last request are returned. + +Optional attributes: + +- ``domain_id`` (string) + +Revoke tokens scoped to a particular domain. + +- ``project_id`` (string) + +Revoke tokens scoped to a particular project. + +- ``user_id`` (string) + +Revoke tokens expressing the identity of a particular user. + +- ``role_id`` (string) + +Revoke tokens issued with a specific role. + +- ``OS-TRUST:trust_id`` (string) + +Revoke tokens issued as the result of a particular trust, as part of the +OS-TRUST API extension. + +- ``OS-OAUTH1:consumer_id`` (string) + +Revoke tokens issued to a specific OAuth consumer, as part of the +OS-OAUTH1 API extension. + +- ``expires_at`` (string, ISO 8601 extended format date time with + microseconds) + +**Deprecated as of the Juno release in favor of ``audit_id`` and +``audit_chain_id``.** If ``expires_at`` exists in the revocation event, +it will be utilized to match tokens. + +Specifies the exact expiration time of one or more tokens to be revoked. + +This attribute is useful for revoking chains of tokens, such as those +produced when re-scoping an existing token. When a token is issued based +on initial authentication, it is given an ``expires_at`` value. When a +token is used to get another token, the new token will have the same +``expires_at`` value as the original. + +- ``audit_id`` (string) + +Specifies the unique identifier (UUID) assigned to the token itself. + +This will revoke a single token only. This attribute mirrors the use of +the ``Token Revocation List`` (the mechanism used prior to revocation +events) but does not utilize data that could convey authorization (the +``token id``). + +If an event is issued for ``audit_id`` then the event cannot contain an +``audit_chain_id``. + +- ``audit_chain_id`` (string) + +Specifies a group of tokens based upon the ``audit_id`` of the first +token in the chain. If a revocation event specifies the +``audit_chain_id`` any token that is part of the token chain (based upon +the original token at the start of the chain) will be revoked, including +the original token at the start of the chain. + +If an event is issued for ``audit_chain_id`` then the event cannot +contain an ``audit_id``. + +The properties are additive: Only a token that meets all of the +specified criteria is considered revoked. + +Minimal example entity: + +:: + + { + "issued_before": "2014-02-27T18:30:59.999999Z" + } + +API +--- + +List revocation events +~~~~~~~~~~~~~~~~~~~~~~ + +:: + + GET /OS-REVOKE/events + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-REVOKE/1.0/rel/events`` + +Optional query parameters: + +- ``since`` (RFC 1123 format date time): limit the list of results to + events that occurred on or after the specified time. + +The HTTP Date header returned in the response reflects the timestamp of +the most recently issued revocation event. Clients can then use this +value in the ``since`` query parameter to limit the list of events in +subsequent requests. + +Response: + +:: + + Status: 200 OK + Date: Sun, 17 Feb 2013 18:30:59 GMT + + { + "events": [ + { + "issued_before": "2014-02-27T18:30:59.999999Z", + "user_id": "f287de" + }, + { + "audit_id": "VcxU2JYqT8OzfUVvrjEITQ", + "issued_before": "2014-02-27T18:30:59.999999Z", + }, + { + "audit_chain_id": "VcxU2JYqT8OzfUVvrjEITQ", + "issued_before": "2014-02-27T18:30:59.999999Z", + "project_id": "976bf9" + }, + { + "domain_id": "be2c70", + "issued_before": "2014-02-2805:15:59.999999Z", + "user_id": "f287de" + } + ] + } + diff --git a/api/identity-api-v3-os-simple-certs-ext.rst b/api/identity-api-v3-os-simple-certs-ext.rst new file mode 100644 index 00000000..0a27905c --- /dev/null +++ b/api/identity-api-v3-os-simple-certs-ext.rst @@ -0,0 +1,197 @@ +OpenStack Identity API v3 OS-SIMPLE-CERT Extension +================================================== + +When using Public Key Infrastructure (PKI) tokens with the identity +service, users must have access to the signing certificate and the +certificate authority's (CA) certificate for the token issuer in order +to validate tokens. This extension provides a simple means of retrieving +these certificates from an identity service. + +API Resources +------------- + +Certificates +------------ + +The identity server uses X.509 certificates to cryptographically sign +issued tokens. Certificates are a public resource and can be shared. +Typically when validating a certificate we would only require the +issuing certificate authority's certificate however PKI tokens are +distributed without including the original signing certificate in the +message so this must be retrievable as well. + +Certificates are provided in the Private Enchanced Mail (PEM) file +format. Certificates in PEM files can be represented with or without the +certificate data (examples shown). The represented certificate is for +informative purposes and the only required information is presented +between the ``-----BEGIN CERTIFICATE-----`` and +``-----END CERTIFICATE-----`` tags. + +API +--- + +Retrieve CA certificate chain +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /OS-SIMPLE-CERT/ca + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-SIMPLE-CERT/1.0/rel/ca_certificate`` + +Fetches the certificate chain used to authenticate signed tokens. + +It is possible that a chain of certificates (more than one) is returned. +In this case the chain should be used when validating a token. + +:: + + Status: 200 OK + Content-Type: application/x-pem-file + + -----BEGIN CERTIFICATE----- + MIIDgTCCAmmgAwIBAgIJAJpWjfJuWL+oMA0GCSqGSIb3DQEBBQUAMFcxCzAJBgNV + BAYTAlVTMQ4wDAYDVQQIDAVVbnNldDEOMAwGA1UEBwwFVW5zZXQxDjAMBgNVBAoM + BVVuc2V0MRgwFgYDVQQDDA93d3cuZXhhbXBsZS5jb20wHhcNMTMxMjA5MDEzMDUw + WhcNMjMxMjA3MDEzMDUwWjBXMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVW5zZXQx + DjAMBgNVBAcMBVVuc2V0MQ4wDAYDVQQKDAVVbnNldDEYMBYGA1UEAwwPd3d3LmV4 + YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxzQwzCPN + 3zMsUX6GwNcS9n/dJq4gzddClFB7ZgfVKOwdEVx/XX9w8wflFWq+JqqMA81ZtLFP + w0fKJFISMSVH7TXPRp096cC41Nv5dCt0kfVChyUUKUGiEzvUU8WagU7uWE4Rj+6d + CQvdbot0/5eDFJL90cj+Ck5dn/lqBxLSnHjTLLqHscpD+qOc6XL4JxCM1SOkS1LL + aRPLksqyKZwz8R86yR/9FnIREGO52VDje0hYUwLw0TzurSi1QHuBB/aZ2aC7A79G + YBBMo79amu8Oc4x+VzOxtY1hlrxYb1oV7SAcZgmPQKo8uwl47yqd5Ya85HC3AsVY + HSGYjsHrTS8QlQIDAQABo1AwTjAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBTkjsL2 + BVqZImdt+VxEo+9b7fymQzAfBgNVHSMEGDAWgBTkjsL2BVqZImdt+VxEo+9b7fym + QzANBgkqhkiG9w0BAQUFAAOCAQEAC7y75ST8tOFp6VOhTTdjGxGU+FJhKNikYCfw + TL5bzjSpmzBXcy5ep+klxVtLyU0KJeuAwep9g6bPlYQP44vshsZEIH4EV5b9Ztzh + FnKfd0jeP0GLhQiQYDkvpNAu/uMbT4+/3jhM3mJoslDZDl7x7MF4FQU0N7fzRj/Y + /XNzA6DWllQs62Up5WcqQJes0NeTKXyLoDH9Mf1W7hLHWLxr5bY3xD2MdrdDTtp1 + KxPZVcFaBpI+hVHfi5jhLXBK0I8jgHqQLxjhp8TfIy6U4m4KpdlOvET2R55Lttrs + SFP+fy+e3IO9wMXmQKQJdj3ArieW0hkmz9xTYIRm5vS494gi6Q== + -----END CERTIFICATE----- + +Retrieve signing certificates +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /OS-SIMPLE-CERT/certificates + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-SIMPLE-CERT/1.0/rel/certificates`` + +Fetches the certificates containing the public key for the private key +that has been used to sign tokens. + +In an environment with multiple token signers this call will return all +valid certificates. + +:: + + Status: 200 OK + Content-Type: application/x-pem-file + + Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, ST=Unset, L=Unset, O=Unset, CN=www.example.com + Validity + Not Before: Dec 9 01:30:50 2013 GMT + Not After : Dec 7 01:30:50 2023 GMT + Subject: C=US, ST=Unset, O=Unset, CN=www.example.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:da:a1:9a:00:3f:52:16:63:87:f7:7c:fb:27:ef: + 04:7b:b3:f8:59:e3:d1:79:cc:22:af:f2:02:5c:d7: + 0f:e8:53:bd:5c:db:a4:93:98:62:25:ad:c9:6e:60: + 37:98:29:c6:e7:0b:3d:b6:64:f6:ad:58:96:e3:87: + af:2a:a4:17:ef:31:3c:60:ef:97:27:db:5e:83:95: + 5b:4f:d6:4b:e8:34:c9:ff:d9:79:bc:f6:7c:db:dc: + d4:91:1b:3d:61:53:54:95:7e:1d:71:dd:9d:cb:39: + e3:ba:ed:39:f4:27:48:60:1b:8d:82:c8:65:e5:a1: + 30:ff:83:bc:84:e8:35:3a:a5:c2:27:7c:84:15:1b: + 91:27:34:44:9d:af:b1:cb:14:54:e0:52:d3:ce:b4: + 03:b7:4c:63:f7:aa:3f:1d:aa:17:ac:2b:81:ec:ad: + e5:30:ac:fa:08:25:00:50:dc:0c:1c:bd:6c:38:eb: + 30:55:5a:e0:ca:11:a8:57:a5:db:65:78:5b:58:76: + f4:01:52:87:4f:d5:a1:80:77:66:8a:2c:d8:77:92: + 11:49:b6:00:fd:28:85:80:23:d7:87:8a:50:15:7d: + 07:2a:6f:44:dc:83:cf:f1:67:5e:8a:9c:b7:2a:2e: + f3:e9:4d:9a:33:9d:e5:1d:7d:3a:9b:ce:80:f4:78: + d7:55 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Subject Key Identifier: + D5:50:6E:6A:AA:8E:21:36:44:28:D4:AB:E4:D3:01:09:D7:BC:CB:73 + X509v3 Authority Key Identifier: + keyid:E4:8E:C2:F6:05:5A:99:22:67:6D:F9:5C:44:A3:EF:5B:ED:FC:A6:43 + + Signature Algorithm: sha1WithRSAEncryption + 80:60:ef:84:25:e9:02:ea:1e:da:70:fe:0b:b6:15:69:27:15: + 0a:8e:5e:69:7b:b3:af:91:0e:78:08:37:98:56:be:eb:60:af: + 7e:6b:e3:62:eb:dc:86:9f:9b:20:81:32:75:05:32:c9:f7:7b: + 2b:32:00:10:83:07:a0:e2:f4:81:63:5e:50:e7:5b:00:67:a6: + 19:54:ea:31:9a:02:a8:f1:fa:92:5b:e1:13:23:a1:28:5c:8e: + 64:03:22:16:02:d2:a5:52:aa:34:39:ab:70:0c:46:77:53:5b: + 07:71:41:0a:0b:a8:76:2c:45:e6:38:3b:aa:ee:dc:ca:8b:2f: + 85:18:57:0a:e3:cf:3d:cc:a8:46:5a:4b:42:14:e8:66:10:8a: + 91:79:c1:2e:27:5f:b1:60:5a:d1:5e:d5:98:c7:11:fe:da:89: + ee:7b:24:e4:19:7a:5f:56:ba:63:70:31:01:87:8d:7a:90:88: + 14:4f:a1:23:46:0e:3b:df:33:01:98:53:71:d6:f4:25:37:52: + ff:43:b8:60:03:65:29:98:45:a8:da:62:a3:be:66:bf:59:68: + 2c:50:3d:de:36:e9:75:8a:d3:69:a2:74:3c:80:c1:fe:cf:53: + 4f:46:28:fe:f9:b0:a9:6a:db:2a:30:9a:e7:b5:c0:cc:0b:d6: + 39:b8:6b:ee + -----BEGIN CERTIFICATE----- + MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBXMQswCQYDVQQGEwJVUzEO + MAwGA1UECAwFVW5zZXQxDjAMBgNVBAcMBVVuc2V0MQ4wDAYDVQQKDAVVbnNldDEY + MBYGA1UEAwwPd3d3LmV4YW1wbGUuY29tMB4XDTEzMTIwOTAxMzA1MFoXDTIzMTIw + NzAxMzA1MFowRzELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVVuc2V0MQ4wDAYDVQQK + DAVVbnNldDEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0B + AQEFAAOCAQ8AMIIBCgKCAQEA2qGaAD9SFmOH93z7J+8Ee7P4WePRecwir/ICXNcP + 6FO9XNukk5hiJa3JbmA3mCnG5ws9tmT2rViW44evKqQX7zE8YO+XJ9teg5VbT9ZL + 6DTJ/9l5vPZ829zUkRs9YVNUlX4dcd2dyznjuu059CdIYBuNgshl5aEw/4O8hOg1 + OqXCJ3yEFRuRJzREna+xyxRU4FLTzrQDt0xj96o/HaoXrCuB7K3lMKz6CCUAUNwM + HL1sOOswVVrgyhGoV6XbZXhbWHb0AVKHT9WhgHdmiizYd5IRSbYA/SiFgCPXh4pQ + FX0HKm9E3IPP8Wdeipy3Ki7z6U2aM53lHX06m86A9HjXVQIDAQABo00wSzAJBgNV + HRMEAjAAMB0GA1UdDgQWBBTVUG5qqo4hNkQo1Kvk0wEJ17zLczAfBgNVHSMEGDAW + gBTkjsL2BVqZImdt+VxEo+9b7fymQzANBgkqhkiG9w0BAQUFAAOCAQEAgGDvhCXp + Auoe2nD+C7YVaScVCo5eaXuzr5EOeAg3mFa+62CvfmvjYuvchp+bIIEydQUyyfd7 + KzIAEIMHoOL0gWNeUOdbAGemGVTqMZoCqPH6klvhEyOhKFyOZAMiFgLSpVKqNDmr + cAxGd1NbB3FBCguodixF5jg7qu7cyosvhRhXCuPPPcyoRlpLQhToZhCKkXnBLidf + sWBa0V7VmMcR/tqJ7nsk5Bl6X1a6Y3AxAYeNepCIFE+hI0YOO98zAZhTcdb0JTdS + /0O4YANlKZhFqNpio75mv1loLFA93jbpdYrTaaJ0PIDB/s9TT0Yo/vmwqWrbKjCa + 57XAzAvWObhr7g== + -----END CERTIFICATE----- + +HTTP Status Codes +~~~~~~~~~~~~~~~~~ + +The following codes are used to indicate success of failure conditions. + +200 OK +^^^^^^ + +Certificates are successfully found and returned. + +403 Forbidden +^^^^^^^^^^^^^ + +There are no certificates to be returned. This will typically indicate +that keystone is using UUID tokens and therefore there are no +certificates available. + +500 Internal Server Error +^^^^^^^^^^^^^^^^^^^^^^^^^ + +An Error was produced on the server. A typical example is that the +server is configured to use PKI tokens but is misconfigured and the +certificates were unable to be found. diff --git a/api/identity-api-v3-os-trust-ext.rst b/api/identity-api-v3-os-trust-ext.rst new file mode 100644 index 00000000..48c722c5 --- /dev/null +++ b/api/identity-api-v3-os-trust-ext.rst @@ -0,0 +1,542 @@ +OpenStack Identity API v3 OS-TRUST Extension +============================================ + +Trusts provide project-specific role delegation between users, with +optional impersonation. + +API Resources +------------- + +Trusts +~~~~~~ + +A trust represents a user's (the *trustor*) authorization to delegate +roles to another user (the *trustee*), and optionally allow the trustee +to impersonate the trustor. After the trustor has created a trust, the +trustee can specify the trust's ``id`` attribute as part of an +authentication request to then create a token representing the delegated +authority. + +The trust contains constraints on the delegated attributes. A token +created based on a trust will convey a subset of the trustor's roles on +the specified project. Optionally, the trust may only be valid for a +specified time period, as defined by ``expires_at``. If no +``expires_at`` is specified, then the trust is valid until it is +explicitly revoked. + +The ``impersonation`` flag allows the trustor to optionally delegate +impersonation abilities to the trustee. To services validating the +token, the trustee will appear as the trustor, although the token will +also contain the ``impersonation`` flag to indicate that this behavior +is in effect. + +A ``project_id`` may not be specified without at least one role, and +vice versa. In other words, there is no way of implicitly delegating all +roles to a trustee, in order to prevent users accidentally creating +trust that are much more broad in scope than intended. A trust without a +``project_id`` or any delegated roles is unscoped, and therefore does +not represent authorization on a specific resource. + +Trusts are immutable. If the trustee wishes to modify the attributes of +the trust, they should create a new trust and delete the old trust. If a +trust is deleted, any tokens generated based on the trust are +immediately revoked. + +If the trustor loses access to any delegated attributes, the trust +becomes immediately invalid and any tokens generated based on the trust +are immediately revoked. + +Additional required attributes: + +- ``trustor_user_id`` (string) + +Represents the user who created the trust, and who's authorization is +being delegated. + +- ``trustee_user_id`` (string) + +Represents the user who is capable of consuming the trust. + +- ``impersonation``: (boolean) + +If ``impersonation`` is set to ``true``, then the ``user`` attribute of +tokens token's generated based on the trust will represent that of the +trustor rather than the trustee, thus allowing the trustee to +impersonate the trustor. If ``impersonation`` is set to ``false``, then +the token's ``user`` attribute will represent that of the trustee. + +Optional attributes: + +- ``project_id`` (string) + +Identifies the project upon which the trustor is delegating +authorization. + +- ``roles``: (list of objects) + +Specifies the subset of the trustor's roles on the ``project_id`` to be +granted to the trustee when the token in consumed. The trustor must +already be granted these roles in the project referenced by the +``project_id`` attribute. + +Roles are only provided when the trust is created, and are subsequently +available as a separate read-only collection. Each role can be specified +by either ``id`` or ``name``. + +- ``expires_at`` (string, ISO 8601 extended format date time with + microseconds) + +Specifies the expiration time of the trust. A trust may be revoked ahead +of expiration. If the value represents a time in the past, the trust is +deactivated. + +- ``remaining_uses`` (integer or null) + +Specifies how many times the trust can be used to obtain a token. This +value is decreased each time a token is issued through the trust. Once +it reaches 0, no further tokens will be issued through the trust. The +default value is null, meaning there is no limit on the number of tokens +issued through the trust. + +Example entity: + +:: + + { + "trust": { + "id": "987fe7", + "impersonation": true, + "project_id": "0f1233", + "remaining_uses": null, + "links": { + "self": "http://identity:35357/v3/trusts/987fe7" + }, + "trustee_user_id": "fea342", + "trustor_user_id": "56aed3" + } + } + +Tokens +~~~~~~ + +Additional attributes: + +- ``trust`` (object) + +If present, indicates that the token was created based on a trust. This +attribute identifies both the trustor and trustee, and indicates whether +the token represents the trustee impersonating the trustor. + +API +--- + +Consuming a trust +~~~~~~~~~~~~~~~~~ + +:: + + POST /auth/tokens + +Consuming a trust effectively assumes the scope as delegated in the +trust. No other scope attributes may be specified. + +The user specified by ``authentication`` must match the trust's +``trustee_user_id`` attribute. + +If the trust has the ``impersonation`` attribute set to ``true``, then +the resulting token's ``user`` attribute will also represent the +trustor, rather than the authenticating user (the trustee). + +:: + + { + "auth": { + "identity": { + "methods": [ + "token" + ], + "token": { + "id": "e80b74" + } + }, + "scope": { + "OS-TRUST:trust": { + "id": "de0945a" + } + } + } + } + +A token created from a trust will have a ``trust`` section containing +the ``id`` of the trust, the ``impersonation`` flag, the +``trustee_user_id`` and the ``trustor_user_id``. Example response: + +:: + + Headers: X-Subject-Token + + X-Subject-Token: e80b74 + + { + "token": { + "expires_at": "2013-02-27T18:30:59.999999Z", + "issued_at": "2013-02-27T16:30:59.999999Z", + "methods": [ + "password" + ], + "OS-TRUST:trust": { + "id": "fe0aef", + "impersonation": false, + "links": { + "self": "http://identity:35357/v3/trusts/fe0aef" + }, + "trustee_user": { + "id": "0ca8f6", + "links": { + "self": "http://identity:35357/v3/users/0ca8f6" + } + }, + "trustor_user": { + "id": "bd263c", + "links": { + "self": "http://identity:35357/v3/users/bd263c" + } + } + }, + "user": { + "domain": { + "id": "1789d1", + "links": { + "self": "http://identity:35357/v3/domains/1789d1" + }, + "name": "example.com" + }, + "email": "joe@example.com", + "id": "0ca8f6", + "links": { + "self": "http://identity:35357/v3/users/0ca8f6" + }, + "name": "Joe" + } + } + } + +Create trust +~~~~~~~~~~~~ + +:: + + POST /OS-TRUST/trusts + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-TRUST/1.0/rel/trusts`` + +Request: + +:: + + { + "trust": { + "expires_at": "2013-02-27T18:30:59.999999Z", + "impersonation": true, + "project_id": "ddef321", + "roles": [ + { + "name": "member" + } + ], + "trustee_user_id": "86c0d5", + "trustor_user_id": "a0fdfd" + } + } + +Response: + +:: + + Status: 201 Created + + { + "trust": { + "expires_at": "2013-02-27T18:30:59.999999Z", + "id": "1ff900", + "impersonation": true, + "links": { + "self": "http://identity:35357/v3/OS-TRUST/trusts/1ff900" + }, + "project_id": "ddef321", + "remaining_uses": null, + "roles": [ + { + "id": "ed7b78", + "links": { + "self": "http://identity:35357/v3/roles/ed7b78" + }, + "name": "member" + } + ], + "roles_links": { + "next": null, + "previous": null, + "self": "http://identity:35357/v3/OS-TRUST/trusts/1ff900/roles" + }, + "trustee_user_id": "86c0d5", + "trustor_user_id": "a0fdfd" + } + } + +List trusts +~~~~~~~~~~~ + +:: + + GET /OS-TRUST/trusts + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-TRUST/1.0/rel/trusts`` + +query\_string: page (optional) query\_string: per\_page (optional, +default 30) query filter for "trustee\_user\_id", "trustor\_user\_id" +(optional) + +Response: + +:: + + Status: 200 OK + + { + "trusts": [ + { + "id": "1ff900", + "expires_at": "2013-02-27T18:30:59.999999Z", + "impersonation": true, + "links": { + "self": "http://identity:35357/v3/OS-TRUST/trusts/1ff900" + }, + "project_id": "0f1233", + "trustee_user_id": "86c0d5", + "trustor_user_id": "a0fdfd" + }, + { + "id": "f4513a", + "impersonation": true, + "links": { + "self": "http://identity:35357/v3/OS-TRUST/trusts/f4513a" + }, + "project_id": "0f1233", + "trustee_user_id": "86c0d5", + "trustor_user_id": "3cd2ce" + } + ] + } + +In order to list trusts for a given trustor, filter the collection using +a query string (e.g., ``?trustor_user_id={user_id}``). + +Request: + +:: + + GET /OS-TRUST/trusts?trustor_user_id=a0fdfd + +Response: + +:: + + Status: 200 OK + + { + "trusts": [ + { + "id": "1ff900", + "expires_at": "2013-02-27T18:30:59.999999Z", + "impersonation": false, + "links": { + "self": "http://identity:35357/v3/OS-TRUST/trusts/1ff900" + }, + "project_id": "0f1233", + "trustee_user_id": "86c0d5", + "trustor_user_id": "a0fdfd" + } + ] + } + +In order to list trusts for a given trustee, filter the collection using +a query string (e.g., ``?trustee_user_id={user_id}``). + +Request: + +:: + + GET /OS-TRUST/trusts?trustee_user_id=86c0d5 + +Response: + +:: + + Status: 200 OK + + { + "trusts": [ + { + "id": "1ff900", + "expires_at": "2013-02-27T18:30:59.999999Z", + "impersonation": true, + "links": { + "self": "http://identity:35357/v3/OS-TRUST/trusts/1ff900" + }, + "project_id": "0f1233", + "trustee_user_id": "86c0d5", + "trustor_user_id": "a0fdfd" + }, + { + "id": "f4513a", + "impersonation": false, + "links": { + "self": "http://identity:35357/v3/OS-TRUST/trusts/f45513a" + }, + "project_id": "0f1233", + "trustee_user_id": "86c0d5", + "trustor_user_id": "3cd2ce" + } + ] + } + +Get trust +~~~~~~~~~ + +:: + + GET /OS-TRUST/trusts/{trust_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-TRUST/1.0/rel/trust`` + +Response: + +:: + + Status: 200 OK + + { + "trust": { + "id": "987fe8", + "expires_at": "2013-02-27T18:30:59.999999Z", + "impersonation": true, + "links": { + "self": "http://identity:35357/v3/OS-TRUST/trusts/987fe8" + }, + "roles": [ + { + "id": "ed7b78", + "links": { + "self": "http://identity:35357/v3/roles/ed7b78" + }, + "name": "member" + } + ], + "roles_links": { + "next": null, + "previous": null, + "self": "http://identity:35357/v3/OS-TRUST/trusts/1ff900/roles" + }, + "project_id": "0f1233", + "trustee_user_id": "be34d1", + "trustor_user_id": "56ae32" + } + } + +Delete trust +~~~~~~~~~~~~ + +:: + + DELETE /OS-TRUST/trusts/{trust_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-TRUST/1.0/rel/trust`` + +Response: + +:: + + Status: 204 No Content + +List roles delegated by a trust +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + GET /OS-TRUST/trusts/{trust_id}/roles + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-TRUST/1.0/rel/trust_roles`` + +Response: + +:: + + Status: 200 OK + + { + "roles": [ + { + "id": "c1648e", + "links": { + "self": "http://identity:35357/v3/roles/c1648e" + }, + "name": "manager" + }, + { + "id": "ed7b78", + "links": { + "self": "http://identity:35357/v3/roles/ed7b78" + }, + "name": "member" + } + ] + } + +Check if role is delegated by a trust +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + HEAD /OS-TRUST/trusts/{trust_id}/roles/{role_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-TRUST/1.0/rel/trust_role`` + +Response: + +:: + + Status: 200 OK + +Get role delegated by a trust +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + GET /OS-TRUST/trusts/{trust_id}/roles/{role_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/ext/OS-TRUST/1.0/rel/trust_role`` + +Response: + +:: + + Status: 200 OK + + { + "role": { + "id": "c1648e", + "links": { + "self": "http://identity:35357/v3/roles/c1648e" + }, + "name": "manager" + } + } + diff --git a/api/identity-api-v3.rst b/api/identity-api-v3.rst new file mode 100644 index 00000000..c8bda48b --- /dev/null +++ b/api/identity-api-v3.rst @@ -0,0 +1,4845 @@ +OpenStack Identity API v3 +========================= + +The Identity API primarily fulfills authentication and authorization +needs within OpenStack, and is intended to provide a programmatic facade +in front of existing authentication and authorization system(s). + +The Identity API also provides endpoint discovery through a service +catalog, identity management, project management, and a centralized +repository for policy engine rule sets. + +What's New in Version 3.3 +------------------------- + +These features are considered stable as of September 4th, 2014. + +- Addition of ``name`` optional variable to be included from service + definition into the service catalog. +- Introduced a stand alone call to retrieve a service catalog. +- Introduced support for JSON Home. +- Introduced a standard call to retrieve possible project and domain + scope targets for a token. +- Addition of ``url`` optional attribute for ``regions``. + +What's New in Version 3.2 +------------------------- + +These features are considered stable as of January 23, 2014. + +- Introduced a mechanism to opt-out from catalog information during + token validation +- Introduced a region resource for constructing a hierarchical + container of groups of service endpoints +- Inexact filtering is supported on string attributes +- Listing collections may indicate only a subset of the data has been + provided if a particular deployment has limited the number of entries + a query may return + +What's New in Version 3.1 +------------------------- + +These features are considered stable as of July 18, 2013. + +- A token without an explicit scope of authorization is issued if the + user does not specify a project and does not have authorization on + the project specified by their default project attribute +- Introduced a generalized call for getting role assignments, with + filtering for user, group, project, domain and role +- Introduced a mechanism to opt-out from catalog information during + token creation +- Added optional bind information to token structure + +What's New in Version 3.0 +------------------------- + +These features are considered stable as of February 20, 2013. + +- Former "Service" and "Admin" APIs (including CRUD operations + previously defined in the v2 OS-KSADM extension) are consolidated + into a single core API +- "Tenants" are now known as "projects" +- "Groups": a container representing a collection of users +- "Domains": a high-level container for projects, users and groups +- "Policies": a centralized repository for policy engine rule sets +- "Credentials": generic credential storage per user (e.g. EC2, PKI, + SSH, etc.) +- Roles can be granted at either the domain or project level +- User, group and project names only have to be unique within their + owning domain +- Retrieving your list of projects (previously ``GET /tenants``) is now + explicitly based on your user ID: ``GET /users/{user_id}/projects`` +- Tokens explicitly represent user+project or user+domain pairs +- Partial updates are performed using the HTTP ``PATCH`` method +- Token ID values no longer appear in URLs + +Document Overview +----------------- + +This document is always evolving as new features are added, use cases +are clarified, etc. API features added since the original publication of +this document are summarized above, grouped by the API version in which +they were first introduced. This document is treated as the single +source of truth for the entire 3.x series of the API. + +A particular implementation of the API is never referenced by name. This +is documentation for the HTTP API itself. Details of the code-base +servicing the API, such as architecture, configuration, and deployment, +are not relevant here. + +The "API Conventions" section defines architectural patterns applied to +the entire API until a portion of the API documents an exception to the +overall conventions. Details of the conventions are not repeated +throughout the document, except in examples, so the reader is expected +to have understood the conventions before reading any further. The goal +is to reduce the cost of documentation maintenance (DRY) and improve +self-consistency across the API, which makes the API more intuitive to +readers and fosters simpler implementations. + +A high level overview of the resources presented by the API are +documented in the "API Resources" section, including required and +optional attributes, use cases and expected behaviors. Specific API +calls are not enumerated, although the feature set of the related calls +should be described if it deviates from the conventions used by the rest +of the API (for example, a resource could be constrained as "a read-only +collection"). + +Finally, the specific calls supported by the API are enumerated with +examples at the end of the document. The examples are intended to be +"realistic" representations of actual requests and responses you could +expect from an implementation of the API. Specifically, the JSON should +be syntactically valid and use data that is self-consistent with related +calls. + +The features described by this document are intended to be applicable to +all implementations of the API. If a particular implementation or +deployment should not be expected to have a use case for a particular +feature, that feature should be documented as an extension to this API. +Extensions may suffix existing resources with their own namespace in +order to add new resources, or prefix new attributes on existing +resource representations. To clearly distinguish extensions from the +core API (which is described by this document) and avoid namespace +collisions between extensions, suffixes and prefixes are composed of an +uppercased abbreviation of the organization supporting the extension +(such as "OS" for OpenStack), followed by a hyphen ("-"), followed by an +uppercased abbreviation of the extension name (such as "OAUTH1" for +OAuth 1.0). Therefore, an extension could be identified as "OS-OAUTH1". + +API Conventions +--------------- + +This section describes architectural patterns applied throughout the +Identity API, unless an exception to these conventions is specifically +documented. In general, the Identity API provides an HTTP interface +using JSON as the primary transport format. + +Each resource contains a canonically unique identifier (ID) defined by +the Identity service implementation and is provided as the ``id`` +attribute; Resource ID's are strings of non-zero length. + +The resource paths of all collections are plural and are represented at +the root of the API (e.g. ``/v3/policies``). + +TCP port 35357 is designated by the Internet Assigned Numbers Authority +("IANA") for use by OpenStack Identity services. Example API requests +and responses in this document therefore assume that the Identity +service implementation is deployed at the root of +``http://identity:35357/``. + +Headers +~~~~~~~ + +- ``X-Auth-Token`` + +This header is used to convey the API user's authentication token when +accessing Identity APIs. + +- ``X-Subject-Token`` + +This header is used to convey the subject of the request for +token-related operations. + +Required Attributes +~~~~~~~~~~~~~~~~~~~ + +For collections: + +- ``links`` (object) + +Specifies a list of relational links to the collection. + +- ``self`` (url) + + A self-relational link provided as an absolute URL. This attribute is + provided by the identity service implementation. + +- ``previous`` (url) + + A relational link to the previous page of the list, provided as an + absolute URL. This attribute is provided by the identity service + implementation. May be null. + +- ``next`` (url) + + A relational to the next page of the list, provided as an absolute + URL. This attribute is provided by the identity service + implementation. May be null. + +For members: + +- ``id`` (string) + +Globally unique resource identifier. This attribute is provided by the +identity service implementation. + +- ``links`` (object) + +Specifies a set of relational links relative to the collection member. + +- ``self`` (url) + + A self-relational link provided as an absolute URL. This attribute is + provided by the identity service implementation. + +Optional Attributes +~~~~~~~~~~~~~~~~~~~ + +For collections: + +- ``truncated`` (boolean) + + In the case where a particular implementation has restricted the + number of entries that can be returned in a collection and not all + entries could be included, the list call will return a status code of + 200 (OK), with ``truncated`` set to ``true``. If this attribute is + not present (or is set to ``false``) then the list represents the + complete collection, unless either the ``next`` or ``previous`` links + are not ``null``, in which case the list represents a page within the + complete collection. + +CRUD Operations +~~~~~~~~~~~~~~~ + +Unless otherwise documented (tokens being the notable exception), all +resources provided by the Identity API support basic CRUD operations +(create, read, update, delete). + +The examples in this section utilize a resource collection of Entities +on ``/v3/entities`` which is not actually a part of the Identity API, +and is used for illustrative purposes only. + +Create an Entity +^^^^^^^^^^^^^^^^ + +When creating an entity, you must provide all required attributes +(except those provided by the Identity service implementation, such as +the resource ID): + +Request: + +:: + + POST /entities + + { + "entity": { + "name": string, + "description": string, + "enabled": boolean + } + } + +The full entity is returned in a successful response (including the new +resource's ID and a self-relational link), keyed by the singular form of +the resource name: + +:: + + 201 Created + + { + "entity": { + "id": string, + "name": string, + "description": string, + "enabled": boolean, + "links": { + "self": url + } + } + } + +List Entities +^^^^^^^^^^^^^ + +Request the entire collection of entities: + +:: + + GET /entities + +A successful response includes a list of anonymous dictionaries, keyed +by the plural form of the resource name (identical to that found in the +resource URL): + +:: + + 200 OK + + { + "entities": [ + { + "id": string, + "name": string, + "description": string, + "enabled": boolean, + "links": { + "self": url + } + }, + { + "id": string, + "name": string, + "description": string, + "enabled": boolean, + "links": { + "self": url + } + } + ], + "links": { + "self": url, + "next": url, + "previous": url + } + } + +List Entities filtered by attribute +''''''''''''''''''''''''''''''''''' + +Beyond each resource's canonically unique identifier (the ``id`` +attribute), not all attributes are guaranteed unique on their own. To +filter a list of resources based on a specific attribute, we can perform +a filtered query using one or more query parameters: + +:: + + GET /entities?name={entity_name}&enabled + +If multiple filters are specified in a query, then all filters must +match for an entity to be included in the response. The values specified +in a filter must be of the same type as the attribute, and in the case +of strings are limited to the same maximum length as the attribute. + +The response is a subset of the full collection: + +:: + + 200 OK + + { + "entities": [ + { + "id": string, + "name": string, + "description": string, + "enabled": boolean, + "links": { + "self": url + } + } + ], + "links": { + "self": url, + "next": url, + "previous": url + } + } + +*New in version 3.2* String attributes may also be filtered using +inexact patterns, for example: + +:: + + GET /entities?name__startswith={initial_characters_of_entity_name} + +The following inexact suffixes are supported: + +- ``__startswith`` + +Matches if the attribute starts with the characters specified, with the +comparison being case-sensitive. + +- ``__istartswith`` + +Matches if the attribute starts with the characters specified, with the +comparison being case-insensitive. + +- ``__endswith`` + +Matches if the attribute ends with the characters specified, with the +comparison being case-sensitive. + +- ``__iendswith`` + +Matches if the attribute ends with the characters specified, with the +comparison being case-insensitive. + +- ``__contains`` + +Matches if the attribute contains the characters specified, with the +comparison being case-sensitive. + +- ``__icontains`` + +Matches if the attribute contains the characters specified, with the +comparison being case-insensitive. + +Inexact filters specified for non-string attributes will be ignored. + +Get an Entity +^^^^^^^^^^^^^ + +Request a specific entity by ID: + +:: + + GET /entities/{entity_id} + +The full resource is returned in response: + +:: + + 200 OK + + { + "entity": { + "id": string, + "name": string, + "description": string, + "enabled": boolean, + "links": { + "self": url + } + } + } + +Nested collections +'''''''''''''''''' + +An entity may contain nested collections, in which case the required +attributes for collections still apply; however, to avoid conflicts with +other required attributes, the required attributes of the collection are +prefixed with the name of the collection. For example, if an ``entity`` +contains a nested collection of ``objects``, the ``links`` for the +collection of ``objects`` is called ``objects_links``: + +:: + + { + "entity": { + "id": string, + "name": string, + "description": string, + "enabled": boolean, + "links": { + "self": url + }, + "objects": [ + { + "id": string, + "name": string, + "description": string, + "enabled": boolean, + "links": { + "self": url + } + } + ], + "objects_links": { + "self": url, + "next": url, + "previous": url + } + } + } + +Update an Entity +^^^^^^^^^^^^^^^^ + +Partially update an entity (unlike a standard ``PUT`` operation, only +the specified attributes are replaced): + +:: + + PATCH /entities/{entity_id} + + { + "entity": { + "description": string + } + } + +The full entity is returned in response: + +:: + + 200 OK + + { + "entity": { + "id": string, + "name": string, + "description": string, + "enabled": boolean, + "links": { + "self": url + } + } + } + +Delete an Entity +^^^^^^^^^^^^^^^^ + +Delete a specific entity by ID: + +:: + + DELETE /entities/{entity_id} + +A successful response does not include a body: + +:: + + 204 No Content + +HTTP Status Codes +~~~~~~~~~~~~~~~~~ + +The Identity API uses a subset of the available HTTP status codes to +communicate specific success and failure conditions to the client. + +200 OK +^^^^^^ + +This status code is returned in response to successful ``GET``, ``HEAD`` +and ``PATCH`` operations. + +201 Created +^^^^^^^^^^^ + +This status code is returned in response to successful ``POST`` +operations. + +204 No Content +^^^^^^^^^^^^^^ + +This status code is returned in response to successful ``HEAD``, ``PUT`` +and ``DELETE`` operations. + +300 Multiple Choices +^^^^^^^^^^^^^^^^^^^^ + +This status code is returned by the root identity endpoint, with +references to one or more Identity API versions (such as ``/v3/``). + +400 Bad Request +^^^^^^^^^^^^^^^ + +This status code is returned when the Identity service fails to parse +the request as expected. This is most frequently returned when a +required attribute is missing, a disallowed attribute is specified (such +as an ``id`` on ``POST`` in a basic CRUD operation), or an attribute is +provided of an unexpected data type. + +The client is assumed to be in error. + +401 Unauthorized +^^^^^^^^^^^^^^^^ + +This status code is returned when either authentication has not been +performed, the provided X-Auth-Token is invalid or authentication +credentials are invalid (including the user, project or domain having +been disabled). + +403 Forbidden +^^^^^^^^^^^^^ + +This status code is returned when the request is successfully +authenticated but not authorized to perform the requested action. + +404 Not Found +^^^^^^^^^^^^^ + +This status code is returned in response to failed ``GET``, ``HEAD``, +``POST``, ``PUT``, ``PATCH`` and ``DELETE`` operations when a referenced +entity cannot be found by ID. In the case of a ``POST`` request, the +referenced entity may be in the request body as opposed to the resource +path. + +409 Conflict +^^^^^^^^^^^^ + +This status code is returned in response to failed ``POST`` and +``PATCH`` operations. For example, when a client attempts to update an +entity's unique attribute which conflicts with that of another entity in +the same collection. + +Alternatively, a client should expect this status code when attempting +to perform the same create operation twice in a row on a collection with +a user-defined and unique attribute. For example, a User's ``name`` +attribute is defined to be unique and user-defined, so making the same +``POST /users`` request twice in a row will result in this status code. + +The client is assumed to be in error. + +500 Internal Server Error +^^^^^^^^^^^^^^^^^^^^^^^^^ + +This status code is returned when an unexpected error has occurred in +the Identity service implementation. + +501 Not Implemented +^^^^^^^^^^^^^^^^^^^ + +This status code is returned when the Identity service implementation is +unable to fulfill the request because it is incapable of implementing +the entire API as specified. + +For example, an Identity service may be incapable of returning an +exhaustive collection of Projects with any reasonable expectation of +performance, or lack the necessary permission to create or modify the +collection of users (which may be managed by a remote system); the +implementation may therefore choose to return this status code to +communicate this condition to the client. + +503 Service Unavailable +^^^^^^^^^^^^^^^^^^^^^^^ + +This status code is returned when the Identity service is unable to +communicate with a backend service, or by a proxy in front of the +Identity service unable to communicate with the Identity service itself. + +API Resources +------------- + +Users: ``/v3/users`` +~~~~~~~~~~~~~~~~~~~~ + +User entities represent individual API consumers and are owned by a +specific domain. + +Role grants explicitly associate users with projects or domains. Each +user-project or user-domain pair can have a unique set of roles granted +on them. + +A user without any role grants is effectively useless from the +perspective of an OpenStack service and should never have access to any +resources. It is allowed, however, as a means of acquiring or loading +users from external sources prior to mapping them to projects. + +Additional required attributes: + +- ``name`` (string) + +Unique user name, within the owning domain. + +Optional attributes: + +- ``domain_id`` (string) + +References the domain which owns the user; if a domain is not specified +by the client, the Identity service implementation will default it to +the domain to which the client's token is scoped. + +- ``default_project_id`` (string) + +References the user's default project against which to authorize, if the +API user does not explicitly specify one when creating a token. Setting +this attribute does not grant any actual authorization on the project, +and is merely provided for the user's convenience. Therefore, the +referenced project does not need to exist within the user's domain. + +*New in version 3.1* If the user does not have authorization to their +default project, the default project will be ignored at token creation. + +- ``description`` (string) + +- ``enabled`` (boolean) + +Setting this value to ``false`` prevents the user from authenticating or +receiving authorization. Additionally, all pre-existing tokens held by +the user are immediately invalidated. Re-enabling a user does not +re-enable pre-existing tokens. + +- ``password`` (string) + +The default form of credential used during authentication. + +Example entity: + +:: + + { + "user": { + "default_project_id": "263fd9", + "domain_id": "1789d1", + "email": "joe@example.com", + "enabled": true, + "id": "0ca8f6", + "links": { + "self": "http://identity:35357/v3/users/0ca8f6" + }, + "name": "Joe" + } + } + +Groups: ``/v3/groups`` +~~~~~~~~~~~~~~~~~~~~~~ + +Group entities represent a collection of Users and are owned by a +specific domain. As with individual users, role grants explicitly +associate groups with projects or domains. A group role grant onto a +project/domain is the equivalent of granting each individual member of +the group the role on that project/domain. Once a group role grant has +been made, the addition or removal of a user to such a group will result +in the automatic granting/revoking of that role to the user, which will +also cause any token containing that user and project/domain to be +revoked. + +As with users, a group entity without any role grants is effectively +useless from the perspective an OpenStack service and should never have +access to any resources. It is allowed, however, as a means of acquiring +or loading users/groups from external sources prior to mapping them to +projects/domains. + +Additional required attributes: + +- ``name`` (string) + +Unique group name, within the owning domain. + +Optional attributes: + +- ``domain_id`` (string) + +References the domain which owns the group; if a domain is not specified +by the client, the Identity service implementation will default it to +the domain to which the client's token is scoped. + +- ``description`` (string) + +Example entity: + +:: + + { + "group": { + "description": "Developers cleared for work on all general projects" + "domain_id": "1789d1", + "id": "70febc", + "links": { + "self": "http://identity:35357/v3/groups/70febc" + }, + "name": "Developers" + } + } + +Credentials: ``/v3/credentials`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Credentials represent arbitrary authentication credentials associated +with a user. A user may have zero or more credentials, each optionally +scoped to a specific project. + +Additional required attributes: + +- ``user_id`` (string) + +References the user which owns the credential. + +- ``type`` (string) + +Representing the credential type, such as ``ec2`` or ``cert``. A +specific implementation may determine the list of supported types. + +- ``blob`` (blob) + +Arbitrary blob of the credential data, to be parsed according to the +``type``. + +Optional attributes: + +- ``project_id`` (string) + +References a project which limits the scope the credential applies to. + +Example entity: + +:: + + { + "credential": { + "blob": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "id": "80239a", + "links": { + "self": "http://identity:35357/v3/credentials/80239a" + }, + "project_id": "263fd9", + "type": "ec2", + "user_id": "0ca8f6" + } + } + +Projects: ``/v3/projects`` +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Projects represent the base unit of "ownership" in OpenStack, in that +all resources in OpenStack should be owned by a specific project +("projects" were also formerly known as "tenants"). A project itself +must be owned by a specific domain. + +Required attributes: + +- ``name`` (string) + +Unique project name, within the owning domain. + +Optional attributes: + +- ``domain_id`` (string) + +References the domain which owns the project; if a domain is not +specified by the client, the Identity service implementation will +default it to the domain to which the client's token is scoped. + +- ``description`` (string) + +- ``enabled`` (boolean) + +Setting this attribute to ``false`` prevents users from authorizing +against this project. Additionally, all pre-existing tokens authorized +for the project are immediately invalidated. Re-enabling a project does +not re-enable pre-existing tokens. + +Example entity: + +:: + + { + "project": { + "domain_id": "1789d1", + "enabled": true, + "id": "263fd9", + "name": "project-x", + "links": { + "self": "http://identity:35357/v3/projects/263fd9" + } + } + } + +Domains: ``/v3/domains`` +~~~~~~~~~~~~~~~~~~~~~~~~ + +Domains represent collections of users, groups and projects. Each is +owned by exactly one domain. Users, however, can be associated with +multiple projects by granting roles to the user on a project (including +projects owned by other domains). + +Each domain defines a namespace in which certain API-visible name +attributes exist, which affects whether those names need to be globally +unique or simply unique within that domain. Within the Identity API, +there are five such name attributes: + +- *Domain Name*: This is always globally unique across all domains. + +- *Role Name*: This is always globally unique across all domains. + +- *User Name*: This is only unique within the owning domain. + +- *Project Name*: This is only unique within the owning domain. + +- *Group Name*: This is only unique within the owning domain. + +Additional required attributes: + +- ``name`` (string) + +Globally unique name. + +Optional attributes: + +- ``description`` (string) + +- ``enabled`` (boolean) + +Setting this attribute to ``false`` prevents users from authorizing +against this domain or any projects owned by this domain, and prevents +users owned by this domain from authenticating or receiving any other +authorization. Additionally, all pre-existing tokens applicable to the +above entities are immediately invalidated. Re-enabling a domain does +not re-enable pre-existing tokens. + +Example entity: + +:: + + { + "domain": { + "enabled": true, + "id": "1789d1", + "links": { + "self": "http://identity:35357/v3/domains/1789d1" + }, + "name": "example.com" + } + } + +Roles: ``/v3/roles/`` +~~~~~~~~~~~~~~~~~~~~~ + +Roles entities are named identifiers used to map a collection of actions +from a user to either a specific project or across an entire domain. + +Additional required attributes: + +- ``name`` (string) + +Globally unique name of the role. + +Example entity: + +:: + + { + "role": { + "id": "76e72a", + "links": { + "self": "http://identity:35357/v3/roles/76e72a" + }, + "name": "admin" + } + } + +Regions: ``/v3/regions`` +~~~~~~~~~~~~~~~~~~~~~~~~ + +*New in version 3.2* + +Region entities represent a general division of an OpenStack deployment. +A region may have zero or more sub-regions associated with it, making a +tree-like structured hierarchy possible for the OpenStack deployment. + +It is important to note that the concept of a Region has no geographical +connotation to it. Deployers are free to use geographical names for +their regions, for example "us-east", but there is no requirement to do +so. + +Optional attributes: + +- ``description`` (string) + +Freeform description field for the deployer to use as they choose to +describe the region. + +- ``parent_region_id`` (string) + +If the region is hierarchically a child of another region, this field +shall be set to the id of the parent region. + +- ``url`` (string) + +*New in version 3.3* A URL field for the deployer to associate with a +region. + +Example entity: + +:: + + { + "region": { + "description": "2nd sub-region inside the US East region.", + "id": "us-east-2", + "links": { + "self": "https://identity:35357/v3/regions/us-east-2" + }, + "parent_region_id": "us-east", + "url": "http://example.com/auth" + } + } + +Services: ``/v3/services`` +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Service entities represent web services in the OpenStack deployment. A +service may have zero or more endpoints associated with it, although a +service with zero endpoints is essentially useless in an OpenStack +configuration. + +Additional required attributes: + +- ``type`` (string) + +Describes the API implemented by the service. The following values are +recognized within the OpenStack ecosystem: ``compute``, ``image``, +``ec2``, ``identity``, ``volume``, ``network``. To support non-core and +future projects, the value should not be validated against this list. + +Optional attributes: + +- ``description`` (string) + +User-facing description of the service. + +- ``enabled`` (boolean) + +Setting this value to ``false`` prevents the service and its endpoints +from appearing in the service catalog. + +- ``name`` (string) + +User-facing name of the service. + +Example entity: + +:: + + { + "service": { + "enabled": true, + "id": "ee057c", + "links": { + "self": "http://identity:35357/v3/services/ee057c" + }, + "name": "Keystone", + "type": "identity" + } + } + +Endpoints: ``/v3/endpoints`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Endpoint entities represent URL endpoints for OpenStack web services. + +Additional required attributes: + +- ``service_id`` (string) + +References the service to which the endpoint belongs. + +- ``interface`` (string) + +Describes the visibility of the endpoint according to one of the +following values: + +:: + + - `public`: intended for consumption by end users, generally on a publicly + available network interface + + - `internal`: intended for consumption by end users, generally on an + unmetered internal network interface + + - `admin`: intended only for consumption by those needing administrative + access to the service, generally on a secure network interface + +- ``url`` (string) + +Fully qualified URL of the service endpoint. + +Optional attributes: + +- ``region`` (string) + +**Deprecated in v3.2**. Use ``region_id`` + +Represents the geographic location of the service endpoint, if relevant +to the deployment. The value of this attribute is intended to be +implementation specific in meaning. + +- ``region_id`` (string) + +Represents the containing region of the service endpoint. *New in v3.2* + +- ``enabled`` (boolean) + +Setting this value to ``false`` prevents the endpoint from appearing in +the service catalog. + +Example entity: + +:: + + { + "endpoint": { + "enabled": true, + "id": "6fedc0", + "interface": "internal", + "links": { + "self": "http://identity:35357/v3/endpoints/6fedc0" + }, + "region_id": "us-east-2", + "service_id": "ee057c", + "url": "http://identity:35357/" + } + } + +Tokens +~~~~~~ + +Tokens represent an authenticated user's identity and, potentially, +explicit authorization on a specific project or domain. + +Tokens are generated by the Identity service via authentication, and may +be subsequently validated and/or revoked. + +Unlike all other resources in the Identity API, ``token`` objects +returned by the API do not have ``id`` attributes. While ``token`` +objects do have identifiers, they are not passed in resource URL's nor +are they included in the objects themselves. Instead, they are passed in +the ``X-Auth-Token`` and ``X-Subject-Token`` headers, along with a +``Vary: X-Auth-Token, X-Subject-Token`` header to inform caches of this +pattern. + +``token`` objects are only created by the identity service +implementation; clients are not expected to create them. Instead, +clients provide the service with ``auth`` objects in exchange for +``token`` objects. + +Required attributes: + +- ``expires_at`` (string, ISO 8601 extended format date time with + microseconds) + +Specifies the expiration time of the token. Once established, a token's +expiration may not be changed. A token may be revoked ahead of +expiration. If the value represents a time in the past, the token is +invalid. + +- ``issued_at`` (string, ISO 8601 extended format date time with + microseconds) + +Specifies the time at which the token was issued. + +- ``user`` (object) + +References the user to which the token belongs. + +Includes the full resource description of a user. + +- ``methods`` (list) + +The ``methods`` attribute indicates the accumulated set of +authentication methods used to obtain the token. For example, if the +token was obtained by ``password`` authentication, it will contain +``password``. Later, if the token is exchanged using the ``token`` +authentication method one or more times, the subsequently created tokens +will contain both ``password`` and ``token`` in their ``methods`` +attribute. + +Notice the difference between ``methods`` and multifactor +authentication. The ``methods`` attribute merely indicates the methods +used to authenticate the user for the given token. It is up to the +client to look for specific methods to determine the total number of +factors. + +- ``audit_ids`` (array) + +The ``audit_ids`` attribute is a list that contains no more than two +elements. Each id in the ``audit_ids`` attribute is a randomly (unique) +generated string that can be used to track the token. + +Each token will have its own unique audit identifier as the first +element of the array. In the case of a token that was rescoped +(exchanged for another token of the same or different scope), there will +be a second audit identifier as the second element of the array. This +conditional second identifier is the audit id string from the original +token (i.e. the first token issued that was not a rescoped token). + +These audit identifiers can be used to track a specific use of token (or +chain of tokens) across multiple requests and endpoints without exposing +the token id to non-privileged users (e.g. via logs). + +Each audit identifier is a short urlsafe string. + +Example token with ``audit_ids`` attribute (first element is the token's +``audit_id``, second is the ``audit_chain_id``): + +:: + + { + "token": { + "expires_at": "2013-02-27T18:30:59.999999Z", + "issued_at": "2013-02-27T16:30:59.999999Z", + "audit_ids": ["VcxU2JYqT8OzfUVvrjEITQ", "qNUTIJntTzO1-XUk5STybw"], + "methods": [ + "password" + ], + "user": { + "domain": { + "id": "1789d1", + "name": "example.com" + } + "email": "joe@example.com", + "id": "0ca8f6", + "name": "Joe" + } + } + } + +Tokens issued prior to the inclusion of the audit id code will lack the +``audit_ids`` attribute. These tokens lacking ``audit_ids`` will +continue to function normally until revoked or expired. All newly issue +tokens will have the expected ``audit_ids`` attribute. + +Optional attributes: + +- ``project`` (object) + +Specifies the project authorization scope of the token. If this +attribute is not provided, then the token is not authorized to access +any project resources. The presence of this attribute conveys +multi-tenancy to cloud services such that they can achieve resource +isolation based on the authorized request context included in the token. +This attribute must not be included if a ``domain`` attribute is +included. A token with project-level authorization does not express any +authorization on any domain-level resource. + +Includes the full resource description of a project. + +- ``domain`` (object) + +Specifies the domain authorization scope of the token. This is to +provide authorization appropriate to domain-level APIs, for example user +and group management within a domain. If this attribute is not provided, +then the token is not authorized to access any domain level resources. +This attribute must not be included if a ``project`` attribute is +included. A token with domain-level authorization does not express any +authorization on any project-level resource. + +Includes the full resource description of a domain. + +- ``catalog`` (list of object) + +Specifies all the services available to/for the token. It is represented +as a list of service dictionaries with the following format: + +:: + + [ + { + "id": "--service-id--", + "type": "--service-type--", + "name": "--service-name--", + "endpoints": [ + { + "id": "--endpoint-id--", + "interface": "--interface-name--", + "region": "--region-name--", + "url": "--endpoint-url--" + }, + ... + ] + }, + ... + ] + +Required attributes for the service object are: + +- ``id``: the service entity id. +- ``type``: Describes the API implemented by the service. + +Optional attributes for the service object are: + +- ``name``: User-facing name of the service. *New in version 3.3* + +Required attributes for the endpoint object are: + +- ``id``: The endpoint entity id. +- ``interface``: The visibility of the endpoint. Should be one of + ``public``, ``internal`` or ``admin``. +- ``url``: Fully qualified URL of the service endpoint. + +Optional attributes for the endpoint object are: + +- ``region``: The geographic location of the service endpoint. + +- ``bind`` (object) *New in version 3.1* + +Token binding refers to the practice of embedding information from +external authentication providers (like a company's Kerberos server) +inside the token such that a client may validate that the token is used +in conjunction with that authentication mechanism. By coupling this +authentication we can prevent re-use of a stolen token as an attacker +would not have access to the external authentication. + +Specifies one or more external authorization mechanisms that can be used +in conjunction with the token for it to be validated by a bind enforcing +client. For example a token may only be used over a Kerberos +authenticated connection or with a specific client certificate. + +Includes one or more mechanism identifiers with protocol specific data. +The officially supported mechanisms are ``kerberos`` and ``x509`` where: + +:: + + - The ``kerberos`` bind payload is of the form: + + "kerberos": { + "principal": "USER@REALM" + } + + where the user's Kerberos principal is "USER@REALM". + + - The ``x509`` bind payload is of the form: + + "x509": { + "fingerprint": "0123456789ABCDEF", + "algorithm": "sha1" + } + + the ``fingerprint`` is the hash of the client certificate to be validated + in the specified algorithm. It should be the hex form without separating + spaces or colons. The only supported ``algorithm`` is currently ``sha1``. + +Example entity: + +:: + + { + "token": { + "expires_at": "2013-02-27T18:30:59.999999Z", + "issued_at": "2013-02-27T16:30:59.999999Z", + "audit_ids": ["VcxU2JYqT8OzfUVvrjEITQ", "qNUTIJntTzO1-XUk5STybw"], + "methods": [ + "password" + ], + "bind": { + "kerberos": { + "principal": "USER@REALM" + } + }, + "user": { + "domain": { + "id": "1789d1", + "name": "example.com" + } + "email": "joe@example.com", + "id": "0ca8f6", + "name": "Joe" + } + } + } + +Policy +~~~~~~ + +Policies represent arbitrarily serialized policy engine rule sets to be +consumed by remote services. + +Additional required attributes: + +- ``blob`` (string) + +The policy rule set itself, as a serialized blob. + +- ``type`` (string) + +The MIME Media Type of the serialized policy blob. + +Example entity: + +:: + + { + "policy": { + "blob": "{\"default\": false}", + "id": "c41a4c", + "links": { + "self": "http://identity:35357/v3/policies/c41a4c" + }, + "type": "application/json" + } + } + +JSON Home +--------- + +*New in version 3.3* + +The Identity API supports JSON Home for resource and extension +discovery. The identity server will return a JSON Home document on a +``GET /v3`` request where the ``Accept`` header indicates that the +response should be ``application/json-home``. The JSON Home document +contains a mapping of "relationships" to the relative path or path +template to the actual resource. + +The JSON Home document includes not only the core APIs that are +supported for that version of the identity API, but also the resources +for the extensions. + +Each of the resources in the Core API below specify the "relationship" +for the resource. A client application can look up the resource path or +path template for a resource by looking for that resource in the JSON +Home document. + +Core API +-------- + +Versions +~~~~~~~~ + +Describe API version +^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /v3/ + +The fields in the ``version`` object are as follows: + +- ``id``: A string with the current version. For V3, it's "v3.0". +- ``status``: A string with the current maturity level of the + specification. This may be one of ``stable``, or ``deprecated``. +- ``updated``: A string with the time when the specification status + last changed in ISO8601 format. For example, "2013-03-06T00:00:00Z". + +Response: + +:: + + Status: 200 OK + + { + "version": { + "id": "v3.0", + "links": [ + { + "href": "http://identity:35357/v3/", + "rel": "self" + } + ], + "status": "stable", + "updated": "2013-03-06T00:00:00Z" + } + } + +*New in version 3.3*: ``GET /v3/`` will return a JSON Home response if +the ``Accept`` header indicates that the client wants an +``application/json-home`` response. Note that the client must check the +``Content-Type`` in the response because older servers will return a +normal JSON response rather than the JSON Home response. See the `JSON +Home spec `__ +for a description of the JSON Home document format. + +The JSON Home document returned includes all the core components and +also the resources for the enabled extensions. Resources for disabled +extensions aren't included. + +Request: + +:: + + GET /v3 + Accept: application/json-home + +Response: + +:: + + { + "resources": { + "http://docs.openstack.org/api/openstack-identity/3/rel/auth_tokens": { + "href": "/auth/tokens" + } + } + } + +Tokens +~~~~~~ + +Use cases: + +- Given a user name and password, get a token to represent the user. +- Given a token, get a list of other domain/projects the user can + access. +- Given a token, validate the token and return user, domain, project, + roles and potential endpoints. +- Given a valid token, request another token with a different + domain/project (change domain/project being represented with the + user). +- Given a valid token, force it's immediate revocation. + +Authenticate +^^^^^^^^^^^^ + +:: + + POST /auth/tokens + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/auth_tokens`` + +Each request to create a token contains an attribute with ``identity`` +information and, optionally, a ``scope`` describing the authorization +scope being requested. Example request structure: + +:: + + { + "auth": { + "identity": { ... }, + "scope": { ... } + } + } + +Authentication: ``authentication`` +'''''''''''''''''''''''''''''''''' + +Authentication is performed by specifying a list of authentication +``methods``, each with a corresponding object, containing any attributes +required by the authentication method. Example request structure for +three arbitrary authentication methods: + +:: + + { + "auth": { + "identity": { + "methods": ["x", "y", "z"], + "x": { ... }, + "y": { ... }, + "z": { ... } + } + } + } + +The ``password`` authentication method +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To authenticate by ``password``, the user must be uniquely identified in +addition to providing a ``password`` attribute. + +The ``user`` may be identified by either ``id`` or ``name``. A user's +``id`` is sufficient to uniquely identify the ``user``. Example request: + +:: + + { + "auth": { + "identity": { + "methods": [ + "password" + ], + "password": { + "user": { + "id": "0ca8f6", + "password": "secretsecret" + } + } + } + } + } + +If the ``user`` is specified by ``name``, then the ``domain`` of the +``user`` must also be specified in order to uniquely identify the +``user``. Example request: + +:: + + { + "auth": { + "identity": { + "methods": [ + "password" + ], + "password": { + "user": { + "domain": { + "id": "1789d1" + }, + "name": "Joe", + "password": "secretsecret" + } + } + } + } + } + +Alternatively, a ``domain`` ``name`` may be used to uniquely identify +the ``user``. Example request: + +:: + + { + "auth": { + "identity": { + "methods": [ + "password" + ], + "password": { + "user": { + "domain": { + "name": "example.com" + }, + "name": "Joe", + "password": "secretsecret" + } + } + } + } + } + +The ``token`` authentication method +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If the authenticating user is already in possession of a valid token, +then that token is sufficient to identity the user. This method is +typically used in combination with request to change authorization +scope. + +:: + + { + "auth": { + "identity": { + "methods": [ + "token" + ], + "token": { + "id": "e80b74" + } + } + } + } + +Scope: ``scope`` +^^^^^^^^^^^^^^^^ + +An authorization scope, including either a ``project`` or ``domain``, +can be optionally specified as part of the request. If both a ``domain`` +and a ``project`` are specified, an HTTP 400 Bad Request will be +returned, as a token cannot be simultaneously scoped to both a +``project`` and ``domain``. + +A ``project`` may be specified by either ``id`` or ``name``. An ``id`` +is sufficient to uniquely identify a ``project``. Example request: + +:: + + { + "auth": { + "identity": { + "methods": [ + "password" + ], + "password": { + "user": { + "id": "0ca8f6", + "password": "secretsecret" + } + } + }, + "scope": { + "project": { + "id": "263fd9" + } + } + } + } + +If a ``project`` is specified by ``name``, then the ``domain`` of the +``project`` must also be specified in order to uniquely identify the +``project``. Example request: + +:: + + { + "auth": { + "identity": { + "methods": [ + "password" + ], + "password": { + "user": { + "id": "0ca8f6", + "password": "secretsecret" + } + } + }, + "scope": { + "project": { + "domain": { + "id": "1789d1" + }, + "name": "project-x" + } + } + } + } + +Alternatively, a ``domain`` ``name`` may be used to uniquely identify +the ``project``. Example request: + +:: + + { + "auth": { + "identity": { + "methods": [ + "password" + ], + "password": { + "user": { + "id": "0ca8f6", + "password": "secretsecret" + } + } + }, + "scope": { + "project": { + "domain": { + "name": "example.com" + }, + "name": "project-x" + } + } + } + } + +A ``domain`` scope may be specified by either the domain's ``id`` or +``name`` with equivalent results. Example request specifying a domain by +``id``: + +:: + + { + "auth": { + "identity": { + "methods": [ + "password" + ], + "password": { + "user": { + "id": "0ca8f6", + "password": "secretsecret" + } + } + }, + "scope": { + "domain": { + "id": "1789d1" + } + } + } + } + +Example request specifying a domain by ``name``: + +:: + + { + "auth": { + "identity": { + "methods": [ + "password" + ], + "password": { + "user": { + "id": "0ca8f6", + "password": "secretsecret" + } + } + }, + "scope": { + "domain": { + "name": "example.com" + } + } + } + } + +If neither a ``project`` nor a ``domain`` is provided for ``scope``, and +the authenticating ``user`` has a defined default project (the user's +``default_project_id`` attribute), then this will be treated as the +preferred authorization scope. If there is no default project defined, +then a token will be issued without an explicit scope of authorization. + +*New in version 3.1* Additionally, if the user's default project is +invalid, a token will be issued without an explicit scope of +authorization. + +Catalog Opt-Out +^^^^^^^^^^^^^^^ + +:: + + POST /v3/auth/tokens?nocatalog + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/auth_tokens`` + +*New in version 3.1* If the caller specifies a ``nocatalog`` query +parameter in the authentication request, then the authentication +response will not contain the service catalog. The service catalog will +otherwise be included in the response by default. + +Authentication responses +'''''''''''''''''''''''' + +A response without an explicit authorization scope does not contain a +``catalog``, ``project``, ``domain`` or ``roles`` but can be used to +uniquely identify the user. Example response: + +:: + + Headers: + X-Subject-Token: e80b74 + + { + "token": { + "expires_at": "2013-02-27T18:30:59.999999Z", + "issued_at": "2013-02-27T16:30:59.999999Z", + "methods": [ + "password" + ], + "user": { + "domain": { + "id": "1789d1", + "name": "example.com" + }, + "id": "0ca8f6", + "name": "Joe" + } + } + } + +Notice that token ID is not part of the token data. Rather, it is +conveyed in the ``X-Subject-Token`` header. + +A token scoped to a ``project`` will also have a service ``catalog``, +along with the user's roles applicable to the ``project``. Example +response: + +:: + + Headers: X-Subject-Token + + X-Subject-Token: e80b74 + + { + "token": { + "catalog": [ + { + "endpoints": [ + { + "id": "39dc322ce86c4111b4f06c2eeae0841b", + "interface": "public", + "region": "RegionOne", + "url": "http://localhost:5000" + }, + { + "id": "ec642f27474842e78bf059f6c48f4e99", + "interface": "internal", + "region": "RegionOne", + "url": "http://localhost:5000" + }, + { + "id": "c609fc430175452290b62a4242e8a7e8", + "interface": "admin", + "region": "RegionOne", + "url": "http://localhost:35357" + } + ], + "id": "4363ae44bdf34a3981fde3b823cb9aa2", + "type": "identity", + "name": "keystone" + } + ], + "expires_at": "2013-02-27T18:30:59.999999Z", + "issued_at": "2013-02-27T16:30:59.999999Z", + "methods": [ + "password" + ], + "project": { + "domain": { + "id": "1789d1", + "name": "example.com" + }, + "id": "263fd9", + "name": "project-x" + }, + "roles": [ + { + "id": "76e72a", + "name": "admin" + }, + { + "id": "f4f392", + "name": "member" + } + ], + "user": { + "domain": { + "id": "1789d1", + "name": "example.com" + }, + "id": "0ca8f6", + "name": "Joe" + } + } + } + +A token scoped to a ``domain`` will also have a service ``catalog`` +along with the user's roles applicable to the ``domain``. Example +response: + +:: + + Headers: X-Subject-Token + + X-Subject-Token: e80b74 + + { + "token": { + "catalog": [ + { + "endpoints": [ + { + "id": "39dc322ce86c4111b4f06c2eeae0841b", + "interface": "public", + "region": "RegionOne", + "url": "http://localhost:5000" + }, + { + "id": "ec642f27474842e78bf059f6c48f4e99", + "interface": "internal", + "region": "RegionOne", + "url": "http://localhost:5000" + }, + { + "id": "c609fc430175452290b62a4242e8a7e8", + "interface": "admin", + "region": "RegionOne", + "url": "http://localhost:35357" + } + ], + "id": "4363ae44bdf34a3981fde3b823cb9aa2", + "type": "identity", + "name": "keystone" + } + ], + "expires_at": "2013-02-27T18:30:59.999999Z", + "issued_at": "2013-02-27T16:30:59.999999Z", + "methods": [ + "password" + ], + "domain": { + "id": "1789d1", + "name": "example.com" + }, + "roles": [ + { + "id": "76e72a", + "name": "admin" + }, + { + "id": "f4f392", + "name": "member" + } + ], + "user": { + "domain": { + "id": "1789d1", + "name": "example.com" + }, + "id": "0ca8f6", + "name": "Joe" + } + } + } + +Authentication failures +''''''''''''''''''''''' + +Several authentication errors are possible, including 403 Forbidden and +409 Conflict, but here's an example of an HTTP 401 Unauthorized +response: + +:: + + Status: 401 Not Authorized + + { + "error": { + "code": 401, + "message": "The request you have made requires authentication", + "title": "Not Authorized" + } + } + +Optionally, the Identity service implementation may return an +``authentication`` attribute to indicate the supported authentication +methods. + +:: + + Status: 401 Not Authorized + + { + "error": { + "code": 401, + "identity": { + "methods": [ + "password", + "token", + "challenge-response" + ] + }, + "message": "Need to authenticate with one or more supported methods", + "title": "Not Authorized" + } + } + +For authentication processes which require multiple round trips, the +Identity service implementation may return an HTTP 401 Not Authorized +with additional information for the next authentication step. + +For example: + +:: + + Status: 401 Not Authorized + + { + "error": { + "code": 401, + "identity": { + "challenge-response": { + "challenge": "What was the zip code of your birthplace?", + "session_id": "123456" + }, + "methods": [ + "challenge-response" + ] + }, + "message": "Additional authentications steps required.", + "title": "Not Authorized" + } + } + +Validate token and get service catalog +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /auth/tokens + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/auth_tokens`` + +To validate a token using the Identity API, pass your own token in the +``X-Auth-Token`` header, and the token to be validated in the +``X-Subject-Token`` header. The Identity service returns a service +catalog in the response. Example request: + +:: + + Headers: + X-Auth-Token: 1dd7e3 + X-Subject-Token: c67580 + +No request body is required. + +The Identity service will return the exact same response as when the +subject token was issued by ``POST /auth/tokens``. + +Validate token +^^^^^^^^^^^^^^ + +:: + + GET /auth/tokens?nocatalog + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/auth_tokens`` + +*New in version 3.2* + +To validate a token using the Identity API without returning a service +catalog in the response. The request has the same format as +``GET /auth/tokens``. + +The Identity service will return the exact same response as when the +subject token was issued by ``POST /auth/tokens?nocatalog``. + +Check token +^^^^^^^^^^^ + +:: + + HEAD /auth/tokens + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/auth_tokens`` + +This call is identical to ``GET /auth/tokens``, but no response body is +provided, even if an error occurs or the token is invalid. + +Response: + +:: + + Status: 200 OK + +Revoke token +^^^^^^^^^^^^ + +:: + + DELETE /auth/tokens + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/auth_tokens`` + +This call is identical to ``HEAD /auth/tokens`` except that the +``X-Subject-Token`` token is immediately invalidated, regardless of its +``expires_at`` attribute. An additional ``X-Auth-Token`` is not +required. The successful response status also differs from +``HEAD /auth/tokens``. + +Response: + +:: + + Status: 204 No Content + +Authentication Specific Routes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The key use cases we need to cover: + +- Fetching a service catalog based upon the current authorization. +- Retrieve available scoping targets based upon the current + authorization. + +Get service catalog +^^^^^^^^^^^^^^^^^^^ + +:: + + GET /auth/catalog + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/auth_catalog`` + +*New in version 3.3* + +This call returns a service catalog for the ``X-Auth-Token`` provided in +the request, even if the token does not contain a catalog itself (for +example, if it was generated using ``?nocatalog``). + +The structure of the ``catalog`` object is identical to that contained +in a ``token``. + +Response: + +:: + + Status: 200 OK + + { + "catalog": [ + { + "endpoints": [ + { + "id": "39dc322ce86c4111b4f06c2eeae0841b", + "interface": "public", + "region": "RegionOne", + "url": "http://localhost:5000" + }, + { + "id": "ec642f27474842e78bf059f6c48f4e99", + "interface": "internal", + "region": "RegionOne", + "url": "http://localhost:5000" + }, + { + "id": "c609fc430175452290b62a4242e8a7e8", + "interface": "admin", + "region": "RegionOne", + "url": "http://localhost:35357" + } + ], + "id": "4363ae44bdf34a3981fde3b823cb9aa2", + "type": "identity", + "name": "keystone" + } + ], + "links": { + "self": "https://identity:35357/v3/catalog", + "previous": null, + "next": null + } + } + +Get available project scopes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /auth/projects + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/auth_projects`` + +*New in version 3.3* + +This call returns the list of projects that are available to be scoped +to based on the ``X-Auth-Token`` provided in the request. + +The structure of the response is exactly the same as listing projects +for a user. + +Response: + +:: + + Status: 200 OK + + { + "projects": [ + { + "domain_id": "1789d1", + "enabled": true, + "id": "263fd9", + "links": { + "self": "https://identity:35357/v3/projects/263fd9" + }, + "name": "Test Group" + }, + { + "domain_id": "1789d1", + "enabled": true, + "id": "50ef01", + "links": { + "self": "https://identity:35357/v3/projects/50ef01" + }, + "name": "Build Group" + } + ], + "links": { + "self": "https://identity:35357/v3/auth/projects", + "previous": null, + "next": null + } + } + +Get available domain scopes +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /auth/domains + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/auth_domains`` + +*New in version 3.3* + +This call returns the list of domains that are available to be scoped to +based on the ``X-Auth-Token`` provided in the request. + +The structure is the same as listing domains. + +Response: + +:: + + Status: 200 OK + + { + "domains": [ + { + "description": "my domain description", + "enabled": true, + "id": "1789d1", + "links": { + "self": "https://identity:35357/v3/domains/1789d1" + }, + "name": "my domain" + }, + { + "description": "description of my other domain", + "enabled": true, + "id": "43e8da", + "links": { + "self": "https://identity:35357/v3/domains/43e8da" + }, + "name": "another domain" + } + ], + "links": { + "self": "https://identity:35357/v3/auth/domains", + "previous": null, + "next": null + } + } + +Catalog +~~~~~~~ + +The key use cases we need to cover: + +- CRUD for regions, services and endpoints +- Retrieving an endpoint URL by service, region, and interface + +List regions +^^^^^^^^^^^^ + +:: + + GET /regions + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/regions`` + +Optional query parameters: + +- ``parent_region_id`` (string) + +Response: + +:: + + Status: 200 OK + + { + "regions": [ + { + "description": "US East Region", + "id": "us-east", + "links": { + "self": "https://identity:35357/v3/regions/us-east", + "child_regions": "https://identity:35357/v3/regions?parent_region_id=us-east" + }, + "parent_region_id": "us-east-coast", + "url": "http://example.com/auth" + }, + ... + ], + "links": { + "self": "https://identity:35357/v3/regions", + "previous": null, + "next": null + } + } + +Get region +^^^^^^^^^^ + +:: + + GET /regions/{region_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/region`` + +Response: + +:: + + Status: 200 OK + + { + "region": { + "description": "US Southwest Region", + "id": "us-southwest", + "links": { + "self": "https://identity:35357/v3/regions/us-southwest", + "child_regions": "http://identity:35357/v3/regions?parent_region_id=us-southwest" + }, + "parent_region_id": "us-west-coast", + "url": "http://example.com/auth" + } + } + +Create region +^^^^^^^^^^^^^ + +:: + + POST /regions + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/regions`` + +Request: + +:: + + { + "region": { + "description": "US West Subregion 1", + "parent_region_id": "829551", + "url": "http://example.com/auth" + } + } + +Response: + +:: + + Status: 201 Created + + { + "region": { + "description": "US West Subregion 1", + "id": "8ebd7f", + "links": { + "self": "https://identity:35357/v3/regions/8ebd7f", + "child_regions": "https://identity:35357/v3/regions?parent_region_id=8ebd7f" + }, + "parent_region_id": "829551", + "url": "http://example.com/auth" + } + } + +- Adding a region with a parent\_region\_id that does not exist should + fail with a ``404 Not Found`` +- Adding a region with a parent\_region\_id that would form a circular + relationship should fail with a ``409 Conflict`` + +Create region with specific ID +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + PUT /regions/{user_defined_region_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/region`` + +Request: + +:: + + { + "region": { + "description": "US Southwest Subregion 1", + "parent_region_id": "us-south", + "url": "http://example.com/auth" + } + } + +Response: + +:: + + Status: 201 Created + + { + "region": { + "description": "US Southwest Subregion 1", + "id": "us-southwest-1", + "links": { + "self": "https://identity:35357/v3/regions/us-southwest-1", + "child_regions": "https://identity:35357/v3/regions?parent_region_id=us-southwest-1" + }, + "parent_region_id": "us-south", + "url": "http://example.com/auth" + } + } + +- The {user\_defined\_region\_id} must be unique to the OpenStack + deployment. If not, a ``409 Conflict`` should be returned. +- The {user\_defined\_region\_id} shall be urlencoded if the ID + contains characters not permitted in a URI. +- Adding a region with a parent\_region\_id that does not exist should + fail with a ``404 Not Found`` +- Adding a region with a parent\_region\_id that would form a circular + relationship should fail with a ``409 Conflict`` + +Update region +^^^^^^^^^^^^^ + +:: + + PATCH /regions/{region_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/region`` + +Request: + +:: + + { + "region": { + "description": "US Southwest Subregion", + "parent_region_id": "us-southwest", + "url": "http://example.com/auth" + } + } + +Response: + +:: + + Status: 200 OK + + { + "region": { + "description": "US Southwest Subregion", + "id": "us-southwest-1", + "links": { + "self": "https://identity:35357/v3/regions/us-southwest-1", + "child_regions": "https://identity:35357/v3/regions?parent_region_id=us-southwest-1" + }, + "parent_region_id": "us-southwest", + "url": "http://example.com/auth" + } + } + +- Updating a region with a parent\_region\_id that does not exist + should fail with a ``404 Not Found`` + +Delete region +^^^^^^^^^^^^^ + +:: + + DELETE /regions/{region_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/region`` + +- Note: deleting a region with child regions should return a + ``409 Conflict`` + +Response: + +:: + + Status: 204 No Content + +List services +^^^^^^^^^^^^^ + +:: + + GET /services + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/services`` + +Optional query parameters: + +- ``name`` (string) *New in version 3.3* +- ``type`` (string) + +Response: + +:: + + Status: 200 OK + + { + "services": [ + { + "description": "OpenStack Volume Service", + "id": "ee057c", + "links": { + "self": "https://identity:35357/v3/services/ee057c" + }, + "name": "Cinder", + "type": "volume" + }, + { + "description": "OpenStack Identity Service", + "id": "5e70df", + "links": { + "self": "https://identity:35357/v3/services/5e70df" + }, + "name": "Keystone", + "type": "identity" + } + ], + "links": { + "self": "https://identity:35357/v3/services", + "previous": null, + "next": null + } + } + +Get service +^^^^^^^^^^^ + +:: + + GET /services/{service_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/service`` + +Response: + +:: + + Status: 200 OK + + { + "service": { + "description": "OpenStack Volume Service", + "id": "ee057c", + "links": { + "self": "https://identity:35357/v3/services/ee057c" + }, + "name": "Cinder", + "type": "volume" + } + } + +Create service +^^^^^^^^^^^^^^ + +:: + + POST /services + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/services`` + +Request: + +:: + + { + "service": { + "description": "OpenStack Compute Service", + "name": "Nova", + "type": "compute" + } + } + +Response: + +:: + + Status: 201 Created + + { + "service": { + "description": "OpenStack Compute Service", + "id": "520ec2", + "links": { + "self": "https://identity:35357/v3/services/520ec2" + }, + "name": "Nova", + "type": "compute" + } + } + +Update service +^^^^^^^^^^^^^^ + +:: + + PATCH /services/{service_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/service`` + +The request block is the same as the one for create service, except that +only the attributes that are being updated need to be included. + +Response: + +:: + + Status: 200 OK + + { + "service": { + "description": "OpenStack Image Service", + "id": "520ec2", + "links": { + "self": "https://identity:35357/v3/services/520ec2" + }, + "name": "Glance", + "type": "image" + } + } + +Delete service +^^^^^^^^^^^^^^ + +:: + + DELETE /services/{service_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/service`` + +- Note: deleting a service when endpoints exist should either 1) delete + all associated endpoints or 2) fail until endpoints are deleted + +Response: + +:: + + Status: 204 No Content + +Endpoints +~~~~~~~~~ + +List endpoints +^^^^^^^^^^^^^^ + +:: + + GET /endpoints + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/endpoints`` + +Optional query parameters: + +- ``interface`` (string) +- ``service_id`` (string) + +Response: + +:: + + Status: 200 OK + + { + "endpoints": [ + { + "enabled": true, + "id": "6fedc0", + "interface": "public", + "links": { + "self": "https://identity:35357/v3/endpoints/6fedc0" + }, + "region_id": "us-east-1", + "service_id": "ee057c", + "url": "https://service.example.com:5000/" + }, + { + "enabled": true, + "id": "d12b15", + "interface": "admin", + "links": { + "self": "https://identity:35357/v3/endpoints/d12b15" + }, + "region_id": "us-east-2", + "service_id": "8ef7de", + "url": "https://service.example.com:35357/" + } + ], + "links": { + "self": "https://identity:35357/v3/endpoints", + "previous": null, + "next": null + } + } + +Get endpoint +^^^^^^^^^^^^ + +:: + + GET /endpoints/{endpoint_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/endpoint`` + +Response: + +:: + + Status: 200 OK + + { + "endpoint": { + "enabled": true, + "id": "6fedc0", + "interface": "public", + "links": { + "self": "https://identity:35357/v3/endpoints/6fedc0" + }, + "region_id": "us-east-2", + "service_id": "ee057c", + "url": "https://service.example.com:5000/" + } + } + +Create endpoint +^^^^^^^^^^^^^^^ + +:: + + POST /endpoints + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/endpoints`` + +Request: + +:: + + { + "endpoint": { + "interface": "admin", + "region_id": "us-east-2", + "url": "https://service.example.com/", + "service_id": "ee057c" + } + } + +Response: + +:: + + Status: 201 Created + + { + "endpoint": { + "enabled": true, + "id": "6fedc0", + "interface": "admin", + "links": { + "self": "https://identity:35357/v3/endpoints/6fedc0" + }, + "region_id": "us-east-2", + "service_id": "ee057c", + "url": "https://service.example.com:35357/" + } + } + +Update endpoint +^^^^^^^^^^^^^^^ + +:: + + PATCH /endpoints/{endpoint_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/endpoint`` + +The request block is the same as the one for create endpoint, except +that only the attributes that are being updated need to be included. + +Response: + +:: + + Status: 200 OK + + { + "endpoint": { + "enabled": true, + "id": "6fedc0", + "interface": "public", + "links": { + "self": "https://identity:35357/v3/endpoints/6fedc0" + }, + "region_id": "us-east-1", + "service_id": "ee057c", + "url": "https://service.example.com:5000/" + } + } + +Delete endpoint +^^^^^^^^^^^^^^^ + +:: + + DELETE /endpoints/{endpoint_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/endpoint`` + +Response: + +:: + + Status: 204 No Content + +Domains +~~~~~~~ + +List domains +^^^^^^^^^^^^ + +:: + + GET /domains + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/domains`` + +Optional query parameters: + +- ``enabled`` (key-only, no value expected) +- ``name`` (string) + +Response: + +:: + + Status: 200 OK + + { + "domains": [ + { + "description": "my domain description", + "enabled": true, + "id": "1789d1", + "links": { + "self": "https://identity:35357/v3/domains/1789d1" + }, + "name": "my domain" + }, + { + "description": "description of my other domain", + "enabled": true, + "id": "43e8da", + "links": { + "self": "https://identity:35357/v3/domains/43e8da" + }, + "name": "another domain" + } + ], + "links": { + "self": "https://identity:35357/v3/domains", + "previous": null, + "next": null + } + } + +Get domain +^^^^^^^^^^ + +:: + + GET /domains/{domain_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/domain`` + +Response: + +:: + + Status: 200 OK + + { + "domain": { + "description": "my domain description", + "enabled": true, + "id": "1789d1", + "links": { + "self": "https://identity:35357/v3/domains/1789d1" + }, + "name": "my domain" + } + } + +Create domain +^^^^^^^^^^^^^ + +:: + + POST /domains + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/domains`` + +Request: + +:: + + { + "domain": { + "description": "my new domain for users", + "enabled": true, + "name": "my new domain" + } + } + +Response: + +:: + + Status: 201 Created + + { + "domain": { + "description": "my new domain for users", + "enabled": true, + "id": "89b3e2", + "links": { + "self": "https://identity:35357/v3/domains/89b3e2" + }, + "name": "my new domain" + } + } + +Update domain +^^^^^^^^^^^^^ + +:: + + PATCH /domains/{domain_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/domain`` + +The request block is the same as the one for create domain, except that +only the attributes that are being updated need to be included. + +Request: + +:: + + { + "domain": { + "description": "my new domain for users and tenants" + } + } + +Response: + +:: + + Status: 200 OK + + { + "domain": { + "description": "my new domain for users and tenants", + "enabled": true, + "id": "89b3e2", + "links": { + "self": "https://identity:35357/v3/domains/89b3e2" + }, + "name": "my new domain" + } + } + +Delete domain +^^^^^^^^^^^^^ + +:: + + DELETE /domains/{domain_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/domain`` + +Deleting a domain will delete all the entities owned by it (Users, +Groups, and Projects), as well as any credentials and role grants that +relate to these entities. + +In order to minimize the risk of an inadvertent deletion of a domain and +its entities, a domain must first be disabled (using the update domain +API) before a successful delete domain API call can be made. Attempting +to delete an enabled domain will result in an HTTP 403 Forbidden +response. + +Response: + +:: + + Status: 204 No Content + +Projects +~~~~~~~~ + +List projects +^^^^^^^^^^^^^ + +:: + + GET /projects + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/projects`` + +Optional query parameters: + +- ``domain_id`` (string) +- ``enabled`` (key-only, no value expected) +- ``name`` (string) + +Response: + +:: + + Status: 200 OK + + { + "projects": [ + { + "domain_id": "1789d1", + "enabled": true, + "id": "263fd9", + "links": { + "self": "https://identity:35357/v3/projects/263fd9" + }, + "name": "Dev Group A" + }, + { + "domain_id": "1789d1", + "enabled": true, + "id": "e56ad3", + "links": { + "self": "https://identity:35357/v3/projects/e56ad3" + }, + "name": "Dev Group B" + } + ], + "links": { + "self": "https://identity:35357/v3/projects", + "previous": null, + "next": null + } + } + +Get project +^^^^^^^^^^^ + +:: + + GET /projects/{project_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/project`` + +Response: + +:: + + Status: 200 OK + + { + "project": { + "domain_id": "1789d1", + "enabled": true, + "id": "263fd9", + "links": { + "self": "https://identity:35357/v3/projects/263fd9" + }, + "name": "Dev Group A" + } + } + +Create project +^^^^^^^^^^^^^^ + +:: + + POST /projects + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/projects`` + +Request: + +:: + + { + "project": { + "description": "Project space for Test Group", + "domain_id": "1789d1", + "enabled": true, + "name": "Test Group" + } + } + +Response: + +:: + + Status: 201 Created + + { + "project": { + "description": "Project space for Test Group", + "domain_id": "1789d1", + "enabled": true, + "id": "d52e32", + "links": { + "self": "https://identity:35357/v3/projects/d52e32" + }, + "name": "Test Group" + } + } + +Update project +^^^^^^^^^^^^^^ + +:: + + PATCH /projects/{project_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/project`` + +The request block is the same as the one for create project, except that +only the attributes that are being updated need to be included. + +Request: + +:: + + { + "project": { + "description": "Project space for Build Group", + "name": "Build Group" + } + } + +Response: + +:: + + Status: 200 OK + + { + "project": { + "description": "Project space for Build Group", + "domain_id": "1789d1", + "enabled": true, + "id": "d52e32", + "links": { + "self": "https://identity:35357/v3/projects/d52e32" + }, + "name": "Build Group" + } + } + +Delete project +^^^^^^^^^^^^^^ + +:: + + DELETE /projects/{project_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/project`` + +:: + + Status: 204 No Content + +Users +~~~~~ + +List users +^^^^^^^^^^ + +:: + + GET /users + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/users`` + +Optional query parameters: + +- ``domain_id`` (string) +- ``enabled`` (key-only, no value expected) +- ``name`` (string) + +Response: + +:: + + Status: 200 OK + + { + "users": [ + { + "default_project_id": "263fd9", + "description": "Admin user", + "domain_id": "1789d1", + "email": "admin@example.com", + "enabled": true, + "id": "0ca8f6", + "links": { + "self": "https://identity:35357/v3/users/0ca8f6" + }, + "name": "admin" + }, + { + "default_project_id": "263fd9", + "description": "John Smith's user", + "domain_id": "1789d1", + "email": "jsmith@example.com", + "enabled": true, + "id": "9fe1d3", + "links": { + "self": "https://identity:35357/v3/users/9fe1d3" + }, + "name": "jsmith" + } + ], + "links": { + "self": "http://identity:35357/v3/users", + "previous": null, + "next": null + } + } + +Get user +^^^^^^^^ + +:: + + GET /users/{user_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/user`` + +Response: + +:: + + Status: 200 OK + + { + "user": { + "default_project_id": "263fd9", + "description": "John Smith's user", + "domain_id": "1789d1", + "email": "jsmith@example.com", + "enabled": true, + "id": "9fe1d3", + "links": { + "self": "https://identity:35357/v3/users/9fe1d3" + }, + "name": "jsmith" + } + } + +List user projects +^^^^^^^^^^^^^^^^^^ + +:: + + GET /users/{user_id}/projects + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/user_projects`` + +Optional query parameters: + +- ``enabled`` (key-only, no value expected) +- ``name`` (string) + +Response: + +:: + + Status: 200 OK + + { + "projects": [ + { + "domain_id": "1789d1", + "enabled": true, + "id": "263fd9", + "links": { + "self": "https://identity:35357/v3/projects/263fd9" + }, + "name": "Test Group" + }, + { + "domain_id": "1789d1", + "enabled": true, + "id": "50ef01", + "links": { + "self": "https://identity:35357/v3/projects/50ef01" + }, + "name": "Build Group" + } + ], + "links": { + "self": "https://identity:35357/v3/users/9fe1d3/projects", + "previous": null, + "next": null + } + } + +List groups of which a user is a member +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /users/{user_id}/groups + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/user_groups`` + +Optional query parameters: + +- ``name`` (string) + +Response: + +:: + + Status: 200 OK + + { + "groups": [ + { + "description": "Developers cleared for work on all general projects" + "domain_id": "1789d1", + "id": "ea167b", + "links": { + "self": "https://identity:35357/v3/groups/ea167b" + }, + "name": "Developers" + }, + { + "description": "Developers cleared for work on secret projects" + "domain_id": "1789d1", + "id": "a62db1", + "links": { + "self": "https://identity:35357/v3/groups/a62db1" + }, + "name": "Secure Developers" + } + ], + "links": { + "self": "http://identity:35357/v3/users/9fe1d3/groups", + "previous": null, + "next": null + } + } + +Create user +^^^^^^^^^^^ + +:: + + POST /users + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/users`` + +Request: + +:: + + { + "user": { + "default_project_id": "263fd9", + "description": "Jim Doe's user", + "domain_id": "1789d1", + "email": "jdoe@example.com", + "enabled": true, + "name": "James Doe", + "password": "secretsecret" + } + } + +Response: + +:: + + Status: 201 Created + + { + "user": { + "default_project_id": "263fd9", + "description": "Jim Doe's user", + "domain_id": "1789d1", + "email": "jdoe@example.com", + "enabled": true, + "id": "ff4e51", + "links": { + "self": "https://identity:35357/v3/users/ff4e51" + }, + "name": "jdoe" + } + } + +Update user +^^^^^^^^^^^ + +:: + + PATCH /users/{user_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/user`` + +The request block is the same as the one for create user, except that +only the attributes that are being updated need to be included. Use this +method attempt to update user password or enable/disable the user. This +may return a HTTP 501 Not Implemented if the back-end driver does not +allow for the functionality. + +Response: + +:: + + Status: 200 OK + + { + "user": { + "default_project_id": "263fd9", + "description": "James Doe's user", + "domain_id": "1789d1", + "email": "jamesdoe@example.com", + "enabled": true, + "id": "ff4e51", + "links": { + "self": "https://identity:35357/v3/users/ff4e51" + }, + "name": "jamesdoe" + } + } + +Delete user +^^^^^^^^^^^ + +:: + + DELETE /users/{user_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/user`` + +Response: + +:: + + Status: 204 No Content + +Change user password +^^^^^^^^^^^^^^^^^^^^ + +:: + + POST /users/{user_id}/password + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/user_change_password`` + +Request: + +:: + + { + "user": { + "password": "old_secretsecret", + "original_password": "secretsecret" + } + } + +Response: + +:: + + Status: 204 No Content + +Groups +~~~~~~ + +Create group +^^^^^^^^^^^^ + +:: + + POST /groups + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/groups`` + +Request: + +:: + + { + "group": { + "description": "--optional--", + "domain_id": "--optional--", + "name": "..." + } + } + +Response: + +:: + + Status: 201 Created + + { + "group": { + "description": "Developers cleared for work on secret projects", + "id": "--group-id--", + "links": { + "self": "http://identity:35357/v3/groups/--group-id--" + }, + "name": "Secure Developers" + } + } + +List groups +^^^^^^^^^^^ + +:: + + GET /groups + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/groups`` + +Optional query parameters: + +- ``domain_id`` (string) +- ``name`` (string) + +Response: + +:: + + Status: 200 OK + + { + "groups": [ + { + "description": "Developers cleared for work on all general projects" + "domain_id": "--domain-id--", + "id": "--group-id--", + "links": { + "self": "http://identity:35357/v3/groups/--group-id--" + }, + "name": "Developers" + }, + { + "description": "Developers cleared for work on secret projects" + "domain_id": "--domain-id--", + "id": "--group-id--", + "links": { + "self": "http://identity:35357/v3/groups/--group-id--" + }, + "name": "Secure Developers" + }, + { + "description": "Testers cleared for work on all general projects" + "domain_id": "--domain-id--", + "id": "--group-id--", + "links": { + "self": "http://identity:35357/v3/groups/--group-id--" + }, + "name": "Testers" + } + ], + "links": { + "self": "http://identity:35357/v3/groups", + "previous": null, + "next": null + } + } + +Get group +^^^^^^^^^ + +:: + + GET /groups/{group_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/group`` + +Response: + +:: + + Status: 200 OK + + { + "group": { + "description": "Developers cleared for work on secret projects", + "id": "--group-id--", + "links": { + "self": "http://identity:35357/v3/groups/--group-id--" + }, + "name": "Secure Developers" + } + } + +List users who are members of a group +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /groups/{group_id}/users + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/group_users`` + +Optional query parameters: + +- ``enabled`` (key-only, no value expected) +- ``name`` (string) + +Response: + +:: + + Status: 200 OK + + { + "users": [ + { + "default_project_id": "--default-project-id--", + "description": "a user", + "domain_id": "--domain-id--", + "email": "...", + "enabled": true, + "id": "--user-id--", + "links": { + "self": "http://identity:35357/v3/users/--user-id--" + }, + "name": "admin" + }, + { + "default_project_id": "--default-project-id--", + "description": "another user", + "domain_id": "--domain-id--", + "email": "...", + "enabled": true, + "id": "--user-id--", + "links": { + "self": "http://identity:35357/v3/users/--user-id--" + }, + "name": "someone" + } + ], + "links": { + "self": "http://identity:35357/v3/groups/--group-id--/users", + "previous": null, + "next": null + } + } + +Update group +^^^^^^^^^^^^ + +:: + + PATCH /groups/{group_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/group`` + +The request block is the same as the one for create group, except that +only the attributes that are being updated need to be included. This may +return a HTTP 501 Not Implemented if the back-end driver doesn't allow +for the functionality. + +Response: + +:: + + Status: 200 OK + + { + "group": { + "description": "Developers cleared for work on secret projects", + "id": "--group-id--", + "links": { + "self": "http://identity:35357/v3/groups/--group-id--" + }, + "name": "Secure Developers" + } + } + +Delete group +^^^^^^^^^^^^ + +:: + + DELETE /groups/{group_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/group`` + +Response: + +:: + + Status: 204 No Content + +Add user to group +^^^^^^^^^^^^^^^^^ + +:: + + PUT /groups/{group_id}/users/{user_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/group_user`` + +Response: + +:: + + Status: 204 No Content + +Remove user from group +^^^^^^^^^^^^^^^^^^^^^^ + +:: + + DELETE /groups/{group_id}/users/{user_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/group_user`` + +Response: + +:: + + Status: 204 No Content + +Check if user is member of group +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + HEAD /groups/{group_id}/users/{user_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/group_user`` + +Response: + +:: + + Status: 204 No Content + +Credentials +~~~~~~~~~~~ + +The key use cases we need to cover: + +- CRUD on a credential + +Create credential +^^^^^^^^^^^^^^^^^ + +:: + + POST /credentials + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/credentials`` + +This example shows creating an EC2 style credential where the +credentials are a combination of access\_key and secret. Other +credentials (such as access\_key) may be supported by simply changing +the content of the key data. + +Request: + +:: + + { + "credential": { + "blob": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "project_id": "0211d7", + "type": "ec2", + "user_id": "f293ba" + } + } + +Response: + +:: + + Status: 201 Created + + { + "credential": { + "blob": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "id": "46322a", + "links": { + "self": "https://identity:35357/v3/credentials/46322a" + }, + "project_id": "0211d7", + "type": "ec2", + "user_id": "f293ba" + } + } + +List credentials +^^^^^^^^^^^^^^^^ + +:: + + GET /credentials + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/credentials`` + +Optional query parameters: + +- ``user_id`` (string) + +Response: + +:: + + Status: 200 OK + + { + "credentials": [ + { + "blob": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "id": "10b182", + "links": { + "self": "https://identity:35357/v3/credentials/10b182" + }, + "project_id": "82cc2f", + "type": "ec2", + "user_id": "27a19b" + }, + { + "blob": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "id": "85d995", + "links": { + "self": "https://identity:35357/v3/credentials/85d995" + }, + "project_id": "82cc2f", + "type": "ec2", + "user_id": "88770a" + } + ], + "links": { + "self": "http://identity:35357/v3/credentials", + "previous": null, + "next": null + } + } + +Get credential +^^^^^^^^^^^^^^ + +:: + + GET /credentials/{credential_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/credential`` + +Response: + +:: + + Status: 200 OK + + { + "credential": { + "blob": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "id": "85d995", + "links": { + "self": "https://identity:35357/v3/credentials/85d995" + }, + "project_id": "82cc2f", + "type": "ec2", + "user_id": "88770a" + } + } + +Update credential +^^^^^^^^^^^^^^^^^ + +:: + + PATCH /credentials/{credential_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/credential`` + +The request block is the same as the one for create credential, except +that only the attributes that are being updated need to be included. + +Response: + +:: + + Status: 200 OK + + { + "credential": { + "blob": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "id": "85d995", + "links": { + "self": "https://identity:35357/v3/credentials/85d995" + }, + "project_id": "6f20ed", + "type": "ec2", + "user_id": "2a64f5" + } + } + +Delete credential +^^^^^^^^^^^^^^^^^ + +:: + + DELETE /credentials/{credential_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/credential`` + +Response: + +:: + + Status: 204 No Content + +Roles +~~~~~ + +The key use cases we need to cover: + +- CRUD on a role +- Associating a role with a project or domain + +Create role +^^^^^^^^^^^ + +:: + + POST /roles + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/roles`` + +Request: + +:: + + { + "role": { + "name": "..." + } + } + +Response: + +:: + + Status: 201 Created + + { + "role": { + "id": "--role-id--", + "links": { + "self": "http://identity:35357/v3/roles/--role-id--" + }, + "name": "a role name" + } + } + +List roles +^^^^^^^^^^ + +:: + + GET /roles + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/roles`` + +Optional query parameters: + +- ``name`` (string) + +Response: + +:: + + Status: 200 OK + + { + "roles": [ + { + "id": "--role-id--", + "links": { + "self": "http://identity:35357/v3/roles/--role-id--" + }, + "name": "a role name" + }, + { + "id": "--role-id--", + "links": { + "self": "http://identity:35357/v3/roles/--role-id--" + }, + "name": "a role name" + } + ], + "links": { + "self": "http://identity:35357/v3/roles", + "previous": null, + "next": null + } + } + +Get role +^^^^^^^^ + +:: + + GET /roles/{role_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/role`` + +Response: + +:: + + Status: 200 OK + + { + "role": { + "id": "--role-id--", + "links": { + "self": "http://identity:35357/v3/roles/--role-id--" + }, + "name": "a role name" + } + } + +Update role +^^^^^^^^^^^ + +:: + + PATCH /roles/{role_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/role`` + +The request block is the same as the one for create role, except that +only the attributes that are being updated need to be included. + +Response: + +:: + + Status: 200 OK + + { + "role": { + "id": "--role-id--", + "links": { + "self": "http://identity:35357/v3/roles/--role-id--" + }, + "name": "a role name" + } + } + +Delete role +^^^^^^^^^^^ + +:: + + DELETE /roles/{role_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/role`` + +Response: + +:: + + Status: 204 No Content + +Grant role to user on domain +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + PUT /domains/{domain_id}/users/{user_id}/roles/{role_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/domain_user_role`` + +Response: + +:: + + Status: 204 No Content + +Grant role to group on domain +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + PUT /domains/{domain_id}/groups/{group_id}/roles/{role_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/domain_group_role`` + +Response: + +:: + + Status: 204 No Content + +List user's roles on domain +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /domains/{domain_id}/users/{user_id}/roles + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/domain_user_roles`` + +Response: + +:: + + Status: 200 OK + + { + "roles": [ + { + "id": "--role-id--", + "links": { + "self": "http://identity:35357/v3/roles/--role-id--" + }, + "name": "--role-name--", + }, + { + "id": "--role-id--", + "links": { + "self": "http://identity:35357/v3/roles/--role-id--" + }, + "name": "--role-name--" + } + ], + "links": { + "self": "http://identity:35357/v3/domains/--domain_id--/users/--user_id--/roles", + "previous": null, + "next": null + } + } + +List group's roles on domain +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /domains/{domain_id}/groups/{group_id}/roles + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/domain_group_roles`` + +Response: + +:: + + Status: 200 OK + + { + "roles": [ + { + "id": "--role-id--", + "links": { + "self": "http://identity:35357/v3/roles/--role-id--" + }, + "name": "--role-name--", + }, + { + "id": "--role-id--", + "links": { + "self": "http://identity:35357/v3/roles/--role-id--" + }, + "name": "--role-name--" + } + ], + "links": { + "self": "http://identity:35357/v3/domains/--domain_id--/groups/--group_id--/roles", + "previous": null, + "next": null + } + } + +Check if user has role on domain +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + HEAD /domains/{domain_id}/users/{user_id}/roles/{role_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/domain_user_role`` + +Response: + +:: + + Status: 204 No Content + +Check if group has role on domain +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + HEAD /domains/{domain_id}/groups/{group_id}/roles/{role_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/domain_group_role`` + +Response: + +:: + + Status: 204 No Content + +Revoke role from user on domain +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + DELETE /domains/{domain_id}/users/{user_id}/roles/{role_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/domain_user_role`` + +Response: + +:: + + Status: 204 No Content + +Revoke role from group on domain +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + DELETE /domains/{domain_id}/groups/{group_id}/roles/{role_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/domain_group_role`` + +Response: + +:: + + Status: 204 No Content + +Grant role to user on project +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + PUT /projects/{project_id}/users/{user_id}/roles/{role_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/project_user_role`` + +Response: + +:: + + Status: 204 No Content + +Grant role to group on project +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + PUT /projects/{project_id}/groups/{group_id}/roles/{role_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/project_group_role`` + +Response: + +:: + + Status: 204 No Content + +List user's roles on project +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /projects/{project_id}/users/{user_id}/roles + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/project_user_roles`` + +Response: + +:: + + Status: 200 OK + + { + "roles": [ + { + "id": "--role-id--", + "links": { + "self": "http://identity:35357/v3/roles/--role-id--" + }, + "name": "--role-name--", + }, + { + "id": "--role-id--", + "links": { + "self": "http://identity:35357/v3/roles/--role-id--" + }, + "name": "--role-name--" + } + ], + "links": { + "self": "http://identity:35357/v3/projects/--project_id--/users/--user_id--/roles", + "previous": null, + "next": null + } + } + +List group's roles on project +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /projects/{project_id}/groups/{group_id}/roles + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/project_group_roles`` + +Response: + +:: + + Status: 200 OK + + { + "roles": [ + { + "id": "--role-id--", + "links": { + "self": "http://identity:35357/v3/roles/--role-id--" + }, + "name": "--role-name--", + }, + { + "id": "--role-id--", + "links": { + "self": "http://identity:35357/v3/roles/--role-id--" + }, + "name": "--role-name--" + } + ], + "links": { + "self": "http://identity:35357/v3/projects/--project_id--/groups/--group_id--/roles", + "previous": null, + "next": null + } + } + +Check if user has role on project +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + HEAD /projects/{project_id}/users/{user_id}/roles/{role_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/project_user_role`` + +Response: + +:: + + Status: 204 No Content + +Check if group has role on project +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + HEAD /projects/{project_id}/groups/{group_id}/roles/{role_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/project_group_role`` + +Response: + +:: + + Status: 204 No Content + +Revoke role from user on project +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + DELETE /projects/{project_id}/users/{user_id}/roles/{role_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/project_user_role`` + +Response: + +:: + + Status: 204 No Content + +Revoke role from group on project +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + DELETE /projects/{project_id}/groups/{group_id}/roles/{role_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/project_group_role`` + +Response: + +:: + + Status: 204 No Content + +List effective role assignments +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + GET /role_assignments + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/role_assignments`` + +*New in version 3.1* + +Optional query parameters: + +- ``group.id`` (string) +- ``role.id`` (string) +- ``scope.domain.id`` (string) +- ``scope.project.id`` (string) +- ``user.id`` (string) +- ``effective`` (key only, no value expected) + +Get a list of role assignments. + +If no query parameters are specified, then this API will return a list +of all role assignments. + +Response: + +:: + + Status: 200 OK + + { + "role_assignments": [ + { + "links": { + "assignment": "http://identity:35357/v3/domains/--domain-id--/users/--user-id--/roles/--role-id--" + }, + "role": { + "id": "--role-id--" + }, + "scope": { + "domain": { + "id": "--domain-id--" + } + }, + "user": { + "id": "--user-id--" + } + }, + { + "group": { + "id": "--group-id--" + }, + "links": { + "assignment": "http://identity:35357/v3/projects/--project-id--/groups/--group-id--/roles/--role-id--" + }, + "role": { + "id": "--role-id--" + }, + "scope": { + "project": { + "id": "--project-id--" + } + } + } + ], + "links": { + "self": "http://identity:35357/v3/role_assignments", + "previous": null, + "next": null + } + } + +Since this list is likely to be very long, this API would typically +always be used with one of more of the filter queries. Some typical +examples are: + +``GET /role_assignments?user.id={user_id}`` would list all role +assignments involving the specified user. + +``GET /role_assignments?scope.project.id={project_id}`` would list all +role assignments involving the specified project. + +Each role assignment entity in the collection contains a link to the +assignment that gave rise to this entity. + +If the query parameter ``effective`` is specified, rather than simply +returning a list of role assignments that have been made, the API +returns a list of effective assignments at the user, project and domain +level, having allowed for the effects of group membership. Since the +effects of group membership have already been allowed for, the group +role assignment entities themselves will not be returned in the +collection. This represents the effective role assignments that would be +included in a scoped token. The same set of query parameters can also be +used in combination with the ``effective`` parameter. For example: + +``GET /role_assignments?user.id={user_id}&effective`` would, in other +words, answer the question "what can this user actually do?". + +``GET +/role_assignments?user.id={user_id}&scope.project.id={project_id}&effective`` +would return the equivalent set of role assignments that would be included in +the token response of a project scoped token. + +An example response for an API call with the query parameter +``effective`` specified is given below: + +Response: + +:: + + Status: 200 OK + + { + "role_assignments": [ + { + "links": { + "assignment": "http://identity:35357/v3/domains/--domain-id--/users/--user-id--/roles/--role-id--" + }, + "role": { + "id": "--role-id--" + }, + "scope": { + "domain": { + "id": "--domain-id--" + } + }, + "user": { + "id": "--user-id--" + } + }, + { + "links": { + "assignment": "http://identity:35357/v3/projects/--project-id--/groups/--group-id--/roles/--role-id--", + "membership": "http://identity:35357/v3/groups/--group-id--/users/--user-id--" + }, + "role": { + "id": "--role-id--" + }, + "scope": { + "project": { + "id": "--project-id--" + } + }, + "user": { + "id": "--user-id--" + } + } + ], + "links": { + "self": "http://identity:35357/v3/role_assignments?effective", + "previous": null, + "next": null + } + } + +The entity ``links`` section of a response using the ``effective`` query +parameter also contains, for entities that are included by virtue of +group membership, a url that can be used to access the membership of the +group. + +Policies +~~~~~~~~ + +The key use cases we need to cover: + +- CRUD on a policy + +Create policy +^^^^^^^^^^^^^ + +:: + + POST /policies + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/policies`` + +Request: + +:: + + { + "blob": "--serialized-blob--", + "type": "--serialization-mime-type--" + } + +Response: + +:: + + Status: 201 Created + + { + "policy": { + "blob": "--serialized-blob--", + "id": "--policy-id--", + "links": { + "self": "http://identity:35357/v3/policies/--policy-id--" + }, + "type": "--serialization-mime-type--" + } + } + +List policies +^^^^^^^^^^^^^ + +:: + + GET /policies + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/policies`` + +Optional query parameters: + +- ``type`` (string) + +Response: + +:: + + Status: 200 OK + + { + "policies": [ + { + "blob": "--serialized-blob--", + "id": "--policy-id--", + "links": { + "self": "http://identity:35357/v3/policies/--policy-id--" + }, + "type": "--serialization-mime-type--" + }, + { + "blob": "--serialized-blob--", + "id": "--policy-id--", + "links": { + "self": "http://identity:35357/v3/policies/--policy-id--" + }, + "type": "--serialization-mime-type--" + } + ], + "links": { + "self": "http://identity:35357/v3/policies", + "previous": null, + "next": null + } + } + +Get policy +^^^^^^^^^^ + +:: + + GET /policies/{policy_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/policy`` + +Response: + +:: + + Status: 200 OK + + { + "policy": { + "blob": "--serialized-blob--", + "id": "--policy-id--", + "links": { + "self": "http://identity:35357/v3/policies/--policy-id--" + }, + "type": "--serialization-mime-type--" + } + } + +Update policy +^^^^^^^^^^^^^ + +:: + + PATCH /policies/{policy_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/policy`` + +The request block is the same as the one for create policy, except that +only the attributes that are being updated need to be included. + +Response: + +:: + + Status: 200 OK + + { + "policy": { + "blob": "--serialized-blob--", + "id": "--policy-id--", + "links": { + "self": "http://identity:35357/v3/policies/--policy-id--" + }, + "type": "--serialization-mime-type--" + } + } + +Delete policy +^^^^^^^^^^^^^ + +:: + + DELETE /policies/{policy_id} + +Relationship: +``http://docs.openstack.org/api/openstack-identity/3/rel/policy`` + +Response: + +:: + + Status: 204 No Content + diff --git a/specs/template.rst b/specs/template.rst index da1a367f..671d1548 100644 --- a/specs/template.rst +++ b/specs/template.rst @@ -38,6 +38,9 @@ Some notes about using this template: having to look at additional files which can not be viewed in gerrit. It will also allow inline feedback on the diagram itself. +If your spec has an impact on the HTTP API, propose the corresponding changes +to the ``api/`` directory for review along with your spec. + Problem Description =================== diff --git a/tox.ini b/tox.ini index 5924a1ae..bffd88e4 100644 --- a/tox.ini +++ b/tox.ini @@ -10,7 +10,7 @@ install_command = pip install -U {opts} {packages} deps = -r{toxinidir}/requirements.txt commands = python setup.py testr --slowest --testr-args='{posargs}' - doc8 specs/ + doc8 api/ specs/ [testenv:venv] commands = {posargs}