diff --git a/website/source/docs/agent/http/query.html.markdown b/website/source/docs/agent/http/query.html.markdown index f38dc1b71715..12553180b327 100644 --- a/website/source/docs/agent/http/query.html.markdown +++ b/website/source/docs/agent/http/query.html.markdown @@ -15,7 +15,7 @@ Prepared queries allow you to register a complex service query and then execute it later via its ID or name to get a set of healthy nodes that provide a given service. This is particularly useful in combination with Consul's [DNS Interface](/docs/agent/dns.html) as it allows for much richer queries than -would be possible given the limited interface DNS provides. +would be possible given the limited syntax DNS provides. The following endpoints are supported: @@ -30,7 +30,11 @@ Not all endpoints support blocking queries and all consistency modes, see details in the sections below. The query endpoints support the use of ACL Tokens. Prepared queries have some -special handling of ACL Tokens that are highlighted in the sections below. +special handling of ACL Tokens that are called out where applicable with the +details of each endpoint. + +See the [Prepared Query ACLs](/docs/internals/acl.html#prepared_query_acls) +internals guide for more details about how prepared query policies work. ### /v1/query @@ -45,7 +49,7 @@ By default, the datacenter of the agent is queried; however, the dc can be provided using the "?dc=" query parameter. If ACLs are enabled, then the client will need to supply a token with `prepared_query` -write priveliges sufficient to match the service name being queried and the `Name` +write privileges sufficient to match the service name being queried and the `Name` given to the query, if any. See also the note about the `Token` field below. The create operation expects a JSON request body that defines the prepared query, @@ -208,7 +212,7 @@ By default, the datacenter of the agent is queried; however, the dc can be provided using the "?dc=" query parameter. If ACLs are enabled, then the client will need to supply a token with `prepared_query` -write priveliges sufficient to match the service name being queried and the `Name` +write privileges sufficient to match the service name being queried and the `Name` given to the query, if any. The body is the same as is used to create a prepared query, as described above. @@ -240,7 +244,7 @@ By default, the datacenter of the agent is queried; however, the dc can be provided using the "?dc=" query parameter. If ACLs are enabled, then the client will need to supply a token with `prepared_query` -write priveliges sufficient to match the service name being queried and the `Name` +write privileges sufficient to match the service name being queried and the `Name` given to the query, if any. No body is required as part of this request. diff --git a/website/source/docs/internals/acl.html.markdown b/website/source/docs/internals/acl.html.markdown index 0a7acc58f9b7..d216be304f26 100644 --- a/website/source/docs/internals/acl.html.markdown +++ b/website/source/docs/internals/acl.html.markdown @@ -149,16 +149,8 @@ access to each API token based on the events they should be able to fire. ### Blacklist mode and Prepared Queries -Versions of Consul after 0.6.3 use a new [`prepared_query` ACL](#prepared_query_acls) -policy to control creating, updating, and deleting prepared queries. If you are -upgrading from a previous version of Consul, you will need to add this policy to -your ACL tokens if you want them to be able to manage prepared queries. - -It is not recommended to open up this policy for "write" by default, since clients -will be able to change any prepared query. Versions 0.6.3 and prior would enforce -that only the token that created a query (or a management token) could update it, -but this behavior has been removed in favor of the new -[`prepared_query` ACL](#prepared_query_acls). +After Consul 0.6.3, significant changes were made to ACLs for prepared queries, +incuding a new `prepared_query` ACL policy. See [Prepared Query ACLs](#prepared_query_acls) below for more details. ### Blacklist mode and Keyring Operations @@ -356,26 +348,109 @@ service, then the DNS interface will return no records when queried for it. ## Prepared Query ACLs -In Consul 0.6, a new [Prepared Query](/docs/agent/http/query.html) feature was -added that allows complex service queries to be defined and then executed later -via an ID or name. - -Consul 0.6.3 and earlier would use the client's service policy to determine if -the client could register a prepared query (the client would need at least "read" -permission to the service). This was easy to use, but it did not allow for very -good control of the prepared query namespace. - -After 0.6.3, we introduced a new `prepared_query` ACL policy type that is used -to control the prepared query namespace. Having "write" access to a given prefix -allows a client to create, update, or delete only prepared queries for services -matching that prefix and with prepared query `Name` fields matching that prefix. - -It is not recommended to open up this policy for "write" by default, since clients -will be able to change any prepared query. Versions 0.6.3 and prior would enforce -that only the token that created a query (or a management token) could update it, -but this behavior has been removed in favor of this new ACL policy. - -Execution of prepared queries is governed by the `Token` captured in the query, -or by the client's ACL Token. See the -[`Token` field documentation](/docs/agent/http/query.html#token) for more -details. +Prepared queries have a more complicated relationship with ACLs than most other +Consul resources because they have a lifecycle related to creating, reading, +updating, and deleting queries, and then a separate lifecycle related to +executing queries. + +As we've gotten feedback from Consul users, we've evolved how prepared queries +use ACLs. In this section we first cover the current implementation, and then we +follow that with details about what's changed between specific versions of Consul. + +#### Managing Prepared Queries + +Managing prepared queries includes creating, reading, updating, and deleting +queries. There are a few variations, each of which uses ACLs in one of two +ways: open, protected by unguessable IDs or closed, managed by ACL policies. +These variations are covered here, with examples: + +* Static queries with no `Name` defined are not controlled by any ACL policies. + These types of queries are meant to be ephemeral and not shared to untrusted + clients, and they are only reachable if the prepared query ID is known. Since + these IDs are generated using the same random ID scheme as ACL Tokens, it is + infeasible to guess them. When listing all prepared queries, only a management + token will be able to see these types, though clients can read instances for + which they have an ID. An example use for this type is a query built by a + startup script, tied to a session, and written to a configuration file for a + process to use via DNS. + +* Static queries with a `Name` defined are controlled by the + [`prepared_query`](/docs/internals/acl.html#prepared_query_acls) ACL policy. + Clients are required to have an ACL token with a prefix sufficient to cover + the name they are trying to manage, with a longest prefix match providing a + way to define more specific policies. Clients can list or read queries for + which they have "read" access based on their prefix, and similar they can + update any queries for which they have "write" access. An example use for + this type is a query with a well-known name (eg. prod-master-customer-db) + that is used and known by many clients to provide geo-failover behavior for + a database. + +#### Executing Pepared Queries + +When prepared queries are executed via DNS lookups or HTTP requests, the +management ACL isn't used in any way. Instead, ACLs are applied to the service +being queried, similar to how other service lookups work, except that prepared +queries have some special behavior related to where the ACL Token comes +from: + +* If an ACL Token was captured when the prepared query was defined, it will be + used to perform the service lookup. This allows queries to be executed by + clients with lesser or even no ACL Token, so this should be used with care. + +* If no ACL Token was captured, then the client's ACL Token will be used to + perform the service lookup. + +* If no ACL Token was captured, and the client has no ACL Token, then the + anonymous token will be used to perform the service lookup. + +Capturing ACL Tokens is analogous to +[PostgreSQL’s](http://www.postgresql.org/docs/current/static/sql-createfunction.html) +`SECURITY DEFINER` attribute which can be set on functions, and using the client's ACL +Token is similar to the complementary `SECURITY INVOKER` attribute. + + +#### ACL Implementation Changes + +Prepared queries were originally introduced in Consul 0.6.0, and ACL behavior remained +unchanged through version 0.6.3, but was then changed to allow better management of the +prepared query namespace. + +These differences are outlined in the table below: + +
Operation | +Version <= 0.6.3 | +Version > 0.6.3 | +
---|---|---|
Create static query without `Name` | +The ACL Token used to create the prepared query is checked to make sure it can access the service being queried. This token is captured as the `Token` to use when executing the prepared query. | +No ACL policies are used as long as no `Name` is defined. No `Token` is captured by default unless specifically supplied by the client when creating the query. | +
Create static query with `Name` | +The ACL Token used to create the prepared query is checked to make sure it can access the service being queried. This token is captured as the `Token` to use when executing the prepared query. | +The client token's `prepared_query` ACL policy is used to determine if the client is allowed to register a query for the given `Name`. No `Token` is captured by default unless specifically supplied by the client when creating the query. | +
Manage static query without `Name` | +The ACL Token used to create the query, or a management token must be supplied in order to perform these operations. | +Any client with the ID of the query can perform these operations. | +
Manage static query with a `Name` | +The ACL token used to create the query, or a management token must be supplied in order to perform these operations. | +Similar to create, the client token's `prepared_query` ACL policy is used to determine if these operations are allowed. | +
List queries | +A management token is required to list any queries. | +The client token's `prepared_query` ACL policy is used to determine which queries they can see. Only management tokens can see prepared queries without `Name`. | +
Execute query | +Since a `Token` is always captured when a query is created, that is used to check access to the service being queried. Any token supplied by the client is ignored. | +The captured token, client's token, or anonymous token is used to filter the results, as described above. | +