Merge "Explain default domain in docs for other services"
This commit is contained in:
commit
739b93269c
@ -2,112 +2,161 @@
|
||||
Keystone for other services
|
||||
===========================
|
||||
|
||||
This document provides a summary of some things that other services
|
||||
need to know about how keystone works. Specifically, we were requested
|
||||
to describe what other services need to know about the v3 API. The v3
|
||||
API was introduced in the Grizzly release, and its use until recently
|
||||
has been hidden from other services since the auth_token middleware
|
||||
translated the token format so that both versions look the same. Once
|
||||
the services need to make use of v3 features they need to know about
|
||||
how it works.
|
||||
This document provides a summary of some things that other services need to
|
||||
know about how keystone works, and specifically about how they can take
|
||||
advantage of the v3 API.
|
||||
|
||||
The v3 API was introduced as a stable API in the Grizzly release and included
|
||||
in the default pipeline ever since. Until recently, its use has been hidden
|
||||
from other services because the ``auth_token`` middleware translated the token
|
||||
format so that both versions look the same. Once the services need to make use
|
||||
of v3 features they need to know about how it works.
|
||||
|
||||
|
||||
Glossary
|
||||
========
|
||||
|
||||
Service
|
||||
OpenStack servers like keystone, nova, glance, etc.
|
||||
OpenStack services like identity, compute, image, etc.
|
||||
|
||||
Project
|
||||
A project is a namespace for a grouping of OpenStack entities. Users must
|
||||
be assigned a role on a project in order to interact with it. Prior to the
|
||||
introduction of the v3 API, projects were referred to as tenants and the
|
||||
term is still used in reference to the v2.0 API.
|
||||
|
||||
|
||||
Token differences
|
||||
=================
|
||||
|
||||
The keystone service runs both v2 and v3, v2 requests go to /v2.0 and v3
|
||||
requests go to /v3. You don't need to "enable" the v3 API in keystone, it is
|
||||
available by default via a separate pipeline from v2.0. If you get a token
|
||||
using the v2 API you can use it to do v3 operations (like list users and
|
||||
stuff). The reverse also works, get a v3 token and use it on v2 works fine.
|
||||
|
||||
You can get a v2 token using POST /v2.0/tokens. You can get a v3 token
|
||||
using POST /v3/auth/tokens. The response is different: the service
|
||||
catalog is a different format, and the v3 token has more fields (user
|
||||
domain, project domain).
|
||||
A project provides namespace and resource isolation for groups of OpenStack
|
||||
entities. Users must be assigned a role on a project in order to interact
|
||||
with it. Prior to the introduction of the v3 API, projects were referred to
|
||||
as tenants and the term is still used in reference to the v2.0 API.
|
||||
|
||||
|
||||
Domains
|
||||
=======
|
||||
|
||||
A major change to v3 is domains. Every project, user, and group is in a domain.
|
||||
This means they have a domain_id. You can have two users with the same name but
|
||||
they must be in different domains, thus usernames are not globally unique
|
||||
across the deployment. Unique identifiers assigned to users from keystone are
|
||||
expected to be unique across the deployment. However, roles are not in domains.
|
||||
A major new feature in v3 is domains. Every project, user, and user group is
|
||||
owned by a domain (reflected by their ``domain_id`` value) which provides them
|
||||
their own namespace. For example, unlike in v2.0, usernames are no longer
|
||||
unique across the deployment. You can have two users with the same name, but
|
||||
they must be in different domains. However, user IDs are assigned to users by
|
||||
keystone and are expected to be unique across the deployment. All of this logic
|
||||
applies to both projects and user groups as well. Note that roles are *not*
|
||||
namespaced by domains.
|
||||
|
||||
One of the great things about domains is that you can have one domain
|
||||
backed by SQL (for service users) and another backed by LDAP (the cloud
|
||||
is deployed into existing infrastructure).
|
||||
One of the great things about domains is that you can have one domain backed by
|
||||
SQL (for service users) and another backed by LDAP (the cloud is deployed into
|
||||
existing infrastructure).
|
||||
|
||||
If you do v2 operations, there's no way to specify the domain, so v2
|
||||
operations all work against the default domain. So if you're stuck with
|
||||
v2 and need to get a token you can only get tokens for users in the
|
||||
default domain. If your default domain is SQL and you have a domain for
|
||||
LDAP users called "ldap" you can't get to the users in LDAP using v2.
|
||||
Also, if your default domain is read-only LDAP then you won't be able
|
||||
to create the service users using v2 clients because any SQL-backed
|
||||
domain is unreachable.
|
||||
The "default" domain
|
||||
====================
|
||||
|
||||
Conventionally the "default" domain has a domain ID of ``default`` and a domain
|
||||
name of ``Default``. It is created by ``keystone-manage db_sync`` and thus
|
||||
should always exist, although the domain ID is configurable in
|
||||
``keystone.conf`` and the domain name is mutable through the v3 API.
|
||||
|
||||
Because only the v3 API is domain-aware, we must work to avoid perceived
|
||||
namespace conflicts to v2.0 clients. The solution to this is to have a single
|
||||
domain serve as the implied namespace for all user and tenant references in
|
||||
v2.0. Thus, v2.0 clients can continue to be domain-unaware and avoid the
|
||||
security risk posed by potential namespace conflicts. *This is the only purpose
|
||||
of the default domain.*
|
||||
|
||||
For example, I could otherwise create a domain in v3, create a user in that
|
||||
domain called "admin", authenticate using v2.0, and a domain-unaware v2.0
|
||||
client might assume I'm the same "admin" user it has seen before and grant me
|
||||
escalated privileges. Instead, users outside of the default domain simply
|
||||
cannot authenticate against v2.0, nor can such tokens with references to users
|
||||
and projects outside the default domain be validated on the v2.0 API.
|
||||
|
||||
From a v2.0 client's perspective, there's no way to specify the domain, so v2.0
|
||||
operations implicitly work against the default domain. So if your client is
|
||||
only capable of using v2.0 and you need to get a token, then you can only get
|
||||
tokens for users and tenants (projects) in the default domain. In the real
|
||||
world, this means that if your default domain is backed by SQL and you have a
|
||||
separate domain for LDAP users, then you can't authenticate as an LDAP user
|
||||
using v2.0. Conversely, if your default domain is backed by a read-only LDAP
|
||||
driver, then you won't be able to create the service users using v2.0 clients
|
||||
because any SQL-backed domain is unreachable.
|
||||
|
||||
From a v3 client's perspective, the default domain is not special, other than
|
||||
the fact that such a domain can generally be assumed to exist (assuming the
|
||||
deployment is also running the v2.0 API). It would be reasonable for a v3
|
||||
client to assume a default user domain ID of ``default`` and a default project
|
||||
domain ID of ``default`` unless overridden by more specific configuration.
|
||||
|
||||
To summarize, avoiding namespace conflicts in the v2.0 API is achieved by
|
||||
limiting the v2.0 API and its clients to working with users and projects which
|
||||
are namespaced by a single, arbitrary domain in v3.
|
||||
|
||||
Token differences
|
||||
=================
|
||||
|
||||
The keystone service runs both v2.0 and v3, where v2.0 requests go to the
|
||||
``/v2.0`` endpoint and v3 requests go to the ``/v3`` endpoint. If you're using
|
||||
the default pipeline that ships with keystone, then you don't need "enable" the
|
||||
v3 API in keystone, as it runs by default as a parallel pipeline to the v2.0
|
||||
API.
|
||||
|
||||
If you get a token using the v2.0 API, then you can use it to do v3 operations
|
||||
(such as list users). The reverse, using a v3 token against v2.0, is possible
|
||||
only in certain circumstances. For example, if you're using a project-scoped
|
||||
token wherein the user and project are both owned by the "default" domain,
|
||||
everything will work. Otherwise, token validation against the v2.0 API will
|
||||
fail.
|
||||
|
||||
You can get a v2.0 token using ``POST /v2.0/tokens``. You can get a v3 token
|
||||
using ``POST /v3/auth/tokens``. Note that the responses are significantly
|
||||
different. For example, the service catalog is in a different format, and the
|
||||
v3 token conveys additional context (such as the user's domain and the
|
||||
project's domain).
|
||||
|
||||
Domain-scoped tokens
|
||||
--------------------
|
||||
|
||||
Domain-scoped tokens are scoped to a domain rather than a project.
|
||||
These are useful for operating against keystone but are useless in
|
||||
other services, so other services don't need to concern themselves with
|
||||
domain-scoped tokens.
|
||||
Domain-scoped tokens are scoped to a domain rather than a project. These are
|
||||
useful for operating against keystone but are generally useless in other
|
||||
services that don't have use cases for domain-level operations. Unless a
|
||||
service has a real case for handling such authorization, they don't need to
|
||||
concern themselves with domain-scoped tokens.
|
||||
|
||||
|
||||
Auth Token middleware
|
||||
=====================
|
||||
|
||||
The auth_token middleware handles token validation for the different services.
|
||||
Conceptually, what happens is that auth_token pulls the token out of the
|
||||
X-Auth-Token header, sends the token to keystone to validate the token and get
|
||||
information about the token (the user, project, and roles), and sets a bunch of
|
||||
environment variables with the user, project, and roles. The services typically
|
||||
take the environment variables, put them in the service's "context", and use
|
||||
the context for policy enforcement via oslo.policy.
|
||||
The ``auth_token`` middleware handles token validation for the different
|
||||
services. Conceptually, what happens is that ``auth_token`` pulls the token out
|
||||
of the ``X-Auth-Token`` request header, validates the token using keystone,
|
||||
produces information about the identity (the API user) and authorization
|
||||
context (the project, roles, etc) of the token, and sets environment variables
|
||||
with that data. The services typically take the environment variables, put them
|
||||
in the service's "context", and use the context for policy enforcement via
|
||||
``oslo.policy``.
|
||||
|
||||
Service tokens
|
||||
--------------
|
||||
|
||||
Service tokens are a new-ish feature where the auth_token middleware
|
||||
will also accept a service token in the "X-Service-Token" header. It
|
||||
does the same thing with the service token as the user token, but the
|
||||
results of the token get stuck in environment variables for the service
|
||||
token (the service user, project, and roles). If the service knows
|
||||
about these then it can put this info in its "context" and use it for
|
||||
policy checks. For example, assuming there's a special policy rule
|
||||
called ``service_role`` that works like the ``role`` rule except checks
|
||||
the service roles, you could have a rule like ``service_role:service
|
||||
and user_id:%(user_id)s`` so that a service token is required along
|
||||
with the user owning the object.
|
||||
Service tokens are a feature where the ``auth_token`` middleware will also
|
||||
accept a service token in the ``X-Service-Token`` header. It does the same
|
||||
thing with the service token as the user token, but the results of the token
|
||||
are passed separately in environment variables for the service token (the
|
||||
service user, project, and roles). If the service knows about these then it can
|
||||
put this info in its "context" and use it for policy checks. For example,
|
||||
assuming there's a special policy rule called ``service_role`` that works like
|
||||
the ``role`` rule except checks the service roles, you could have an
|
||||
``oslo.policy`` rule like ``service_role:service and user_id:%(user_id)s`` such
|
||||
that a service token is required along with the user owning the object.
|
||||
|
||||
V2 / V3
|
||||
-------
|
||||
v2.0 or v3?
|
||||
-----------
|
||||
|
||||
The auth_token middleware can be configured to authenticate tokens
|
||||
using v2, v3, or to use discovery (the default). When discovery is
|
||||
used, auth_token will pick v3 if the server reports that v3 is
|
||||
available. If auth_token is configured to use v2 then if it receives a
|
||||
v3 token it will fail if the user is not in the default domain (e.g.,
|
||||
the domain that heat creates users in). So auth_token middleware needs
|
||||
to use v3!
|
||||
By default, the ``auth_token`` middleware will use discovery to determine the
|
||||
best available API to use, or can be explicitly configured to use either v2.0
|
||||
or v3. When discovery is used, ``auth_token`` will use v3 if keystone reports
|
||||
that v3 is available. If ``auth_token`` is configured to use v2.0, then it will
|
||||
fail when it receives a v3 token wherein the user is not in the default domain
|
||||
(for example, the domain that heat creates users in). So if at all possible,
|
||||
the ``auth_token`` middleware should be allowed to use v3.
|
||||
|
||||
Additionally, as other services begin to utilize features which are only found
|
||||
in the v3 API, you'll need to use the v3 API in order to utilize those
|
||||
services. For example, heat creates users in an isolated domain, and thus
|
||||
requires the v3 API.
|
||||
|
||||
Do this, not that
|
||||
=================
|
||||
@ -115,39 +164,37 @@ Do this, not that
|
||||
Config options for authentication
|
||||
---------------------------------
|
||||
|
||||
If you need to get a token, don't define options for username and
|
||||
password and get a token using v2. We've got an interface for using
|
||||
authentication plugins where there's an option for that supports v2 or
|
||||
v3 and potentially other authentication mechanisms (X.509 client
|
||||
certs!).
|
||||
If you need to get a token, don't define options for username and password and
|
||||
get a token using v2.0. We've got an interface for using authentication plugins
|
||||
where there's an option for that supports v2.0 or v3 and potentially other
|
||||
authentication mechanisms (X.509 client certs!).
|
||||
|
||||
If your config file doesn't have the domain for the user, it's not
|
||||
going to be able to use v3 for authentication.
|
||||
If your config file doesn't have the domain for the user, it's not going to be
|
||||
able to use v3 for authentication.
|
||||
|
||||
Picking the version
|
||||
-------------------
|
||||
|
||||
Use version discovery to figure out what version the identity server
|
||||
supports rather than configuring the version.
|
||||
Use version discovery to figure out what version the identity server supports
|
||||
rather than configuring the version.
|
||||
|
||||
Use OpenStack CLI not keystone CLI
|
||||
----------------------------------
|
||||
|
||||
The keystone CLI is deprecated and will be removed soon. The `OpenStack CLI
|
||||
<http://docs.openstack.org/developer/python-openstackclient/>`_
|
||||
has all the keystone CLI commands and even supports v3.
|
||||
<http://docs.openstack.org/developer/python-openstackclient/>`_ has all the
|
||||
keystone CLI commands and even supports v3.
|
||||
|
||||
|
||||
Hierarchical Multitenancy
|
||||
=========================
|
||||
|
||||
This feature allows maintenance of a hierarchy of projects with
|
||||
"parent" projects operating as domains.
|
||||
This feature allows maintenance of a hierarchy of projects with "parent"
|
||||
projects operating as domains.
|
||||
|
||||
The token format is the same (the token doesn't contain any info about
|
||||
the hierarchy). If the service needs to know the hierarchy it will have
|
||||
to use the v3 API to fetch the hierarchy.
|
||||
The token format is the same (the token doesn't contain any info about the
|
||||
hierarchy). If the service needs to know the hierarchy it will have to use the
|
||||
v3 API to fetch the hierarchy.
|
||||
|
||||
While you can't use v2 to set up the hierarchy, you can get a v2 token
|
||||
While you can't use v2.0 to set up the hierarchy, you can get a v2.0 token
|
||||
scoped to a project that's part of a hierarchy.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user