Amendments to the introduction of policy.json
This is an amendment of https://review.openstack.org/#/c/166853/, after additional information became available. Specifically, information about the is_admin flag and a note on tweaking policy.json are added, and some points reworded for clarity. While there is still room for improvement, the bug, previously declared as partially fixed, can be closed now. Change-Id: Ifd01bc4e367f65d6ce45c54a005bafb660535260 Closes-Bug: #1311067
This commit is contained in:
parent
845400dbe9
commit
683999e929
@ -11,23 +11,44 @@
|
||||
|
||||
<para>Each OpenStack service, Identity, Compute, Networking and so on, has its own
|
||||
role-based access policies. They determine which user can access which objects in
|
||||
which way, and are defined in the service’s <filename>policy.json</filename>
|
||||
which way, and are defined in the service's <filename>policy.json</filename>
|
||||
file.</para>
|
||||
|
||||
<para>Whenever an API call to an OpenStack service is made, the service’s policy
|
||||
<para>Whenever an API call to an OpenStack service is made, the service's policy
|
||||
engine uses the appropriate policy definitions to determine if the call can be
|
||||
accepted. Any changes to <filename>policy.json</filename> are effective immediately,
|
||||
which allows
|
||||
new policies to be implemented while the service is running.</para>
|
||||
|
||||
<para>As the name implies, <filename>policy.json</filename> files are in JSON (Javascript
|
||||
Object Notation) format. A policy is defined by a statement with the general form
|
||||
<code>"<target>" : "<rule>"</code>.
|
||||
<para>A <filename>policy.json</filename> file is a text file in JSON (Javascript
|
||||
Object Notation) format. Each policy is defined by a one-line statement in the form
|
||||
<literal>"<target>" : "<rule>"</literal>.</para>
|
||||
|
||||
A target, also named “action”, is an API call, such as “start an instance” or
|
||||
“attach a volume”. The rule determines under which circumstances the API call
|
||||
is permitted. In most cases, these circumstances involve the user who makes the
|
||||
call, thereafter named the “API user” for simplicity.</para>
|
||||
<para>
|
||||
The policy target, also named "action", represents an API call like "start an instance" or
|
||||
"attach a volume".
|
||||
</para>
|
||||
|
||||
<para>Action names are usually qualified.
|
||||
Example: OpenStack Compute features API calls to list instances,
|
||||
volumes and networks. In <filename>/etc/nova/policy.json</filename>, these APIs are
|
||||
represented by <literal>compute:get_all</literal>, <literal>volume:get_all</literal>
|
||||
and <literal>network:get_all</literal>, respectively.</para>
|
||||
|
||||
<para>The mapping between API calls and actions is not generally documented.</para>
|
||||
|
||||
<para>The policy rule determines under which circumstances the API call
|
||||
is permitted. Usually this involves the user who makes the
|
||||
call (hereafter named the "API user") and often the object on which the
|
||||
API call operates. A typical rule checks if the API user is the object's owner.</para>
|
||||
|
||||
<caution><title>Modifying the policy</title>
|
||||
<para>
|
||||
While recipes for editing <filename>policy.json</filename> files
|
||||
are found on blogs, modifying the policy can have unexpected side effects and is
|
||||
not encouraged.
|
||||
</para>
|
||||
</caution>
|
||||
|
||||
<section xml:id="Examples">
|
||||
<title>Examples</title>
|
||||
@ -36,19 +57,19 @@
|
||||
|
||||
<programlisting language="json">"compute:get_all" : ""</programlisting>
|
||||
|
||||
The target is <code>"compute:get_all"</code>, the “list all instances” API
|
||||
of the Compute service. The rule is an empty string meaning “always”. This policy
|
||||
The target is <literal>"compute:get_all"</literal>, the "list all instances" API
|
||||
of the Compute service. The rule is an empty string meaning "always". This policy
|
||||
allows anybody to list instances.</para>
|
||||
|
||||
<para>You can also decline permission to use an API:
|
||||
|
||||
<programlisting language="json">"compute:shelve": "!"</programlisting>
|
||||
|
||||
The exclamation mark stands for “never” or “nobody”, which effectively disables
|
||||
the Compute API “shelve an instance”.</para>
|
||||
The exclamation mark stands for "never" or "nobody", which effectively disables
|
||||
the Compute API "shelve an instance".</para>
|
||||
|
||||
<para>Many APIs can only be called by admin users. This can be expressed by the rule
|
||||
<code>"role:admin"</code>, which checks whether the API user has the admin role.
|
||||
<literal>"role:admin"</literal>.
|
||||
The following policy ensures that only administrators can create new users in the
|
||||
Identity database:
|
||||
|
||||
@ -56,12 +77,12 @@
|
||||
</para>
|
||||
|
||||
<para>You can limit APIs to any role. For example, the Orchestration service defines
|
||||
a role named <code>heat_stack_user</code>. Whoever has this role isn't allowed to create stacks:
|
||||
a role named <literal>heat_stack_user</literal>. Whoever has this role isn't allowed to create stacks:
|
||||
|
||||
<programlisting language="json">"stacks:create": "not role:heat_stack_user"</programlisting>
|
||||
|
||||
This rule makes use of the boolean operator <code>not</code>.
|
||||
More complex rules can be built using operators <code>and</code>, <code>or</code>
|
||||
This rule makes use of the boolean operator <literal>not</literal>.
|
||||
More complex rules can be built using operators <literal>and</literal>, <literal>or</literal>
|
||||
and parentheses.</para>
|
||||
|
||||
<para>You can define aliases for rules:
|
||||
@ -69,7 +90,7 @@
|
||||
<programlisting language="json">"deny_stack_user": "not role:heat_stack_user"</programlisting>
|
||||
|
||||
The policy engine
|
||||
understands that <code>"deny_stack_user"</code> is not an API and consequently
|
||||
understands that <literal>"deny_stack_user"</literal> is not an API and consequently
|
||||
interprets it as an alias. The stack creation policy above can then be written as:
|
||||
|
||||
<programlisting language="json">"stacks:create": "rule:deny_stack_user"</programlisting>
|
||||
@ -80,11 +101,11 @@
|
||||
|
||||
<programlisting language="json">"compute:start" : "user_id:%(user_id)s"</programlisting>
|
||||
|
||||
states that only the owner of an instance can start it up. The <code>user_id</code>
|
||||
states that only the owner of an instance can start it up. The <literal>user_id</literal>
|
||||
string
|
||||
before the colon is an API attribute, namely the user ID of the API user.
|
||||
It is compared with the user ID of the object (in this case, an instance); more
|
||||
precisely, it is compared with the <code>user_id</code> field of that object
|
||||
precisely, it is compared with the <literal>user_id</literal> field of that object
|
||||
in the database. If the two values are equal, permission is
|
||||
granted.</para>
|
||||
|
||||
@ -96,29 +117,40 @@
|
||||
"admin_or_owner": "rule:admin_required or rule:owner",
|
||||
"identity:change_password": "rule:admin_or_owner"</programlisting>
|
||||
|
||||
The first two lines define aliases for
|
||||
"user is an admin user" and "user owns the object", respectively.
|
||||
<code>is_admin</code> in line 1 is a flag that indicates an
|
||||
admin user. While it looks redundant to <code>role:admin</code>, it allows
|
||||
administrative users that don't have the admin role.
|
||||
The <code>owner</code> alias (line 2) compares the API's user ID with the object's user ID.
|
||||
The first line defines an alias for "user is an admin user".
|
||||
The <literal>is_admin</literal> flag is only used when setting
|
||||
up the Identity service for the first time. It indicates that the user
|
||||
has admin privileges granted by the service token
|
||||
(<parameter>--os-token</parameter>
|
||||
parameter of the <command>keystone</command> command line client).
|
||||
</para>
|
||||
|
||||
Line 3 defines a third alias <code>admin_or_owner</code>, combining
|
||||
the two first aliases with the Boolean operator <code>or</code>.
|
||||
Line 4, then, sets up the policy that
|
||||
a password can only be modified by its owner or an admin user.</para>
|
||||
<para>The second line creates an alias for "user owns the object" by comparing
|
||||
the API's user ID with the object's user ID.
|
||||
</para>
|
||||
|
||||
<para>As a final example, let's examine a more complex rule:
|
||||
<para>Line 3 defines a third alias <literal>admin_or_owner</literal>, combining
|
||||
the two first aliases with the Boolean operator <literal>or</literal>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Line 4 sets up the policy that
|
||||
a password can only be modified by its owner or an admin user.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
As a final example, let's examine a more complex rule:
|
||||
|
||||
<programlisting language="json">"identity:ec2_delete_credential": "rule:admin_required or
|
||||
(rule:owner and user_id:%(target.credential.user_id)s)"
|
||||
</programlisting>
|
||||
|
||||
It determines who can use the Identity API “delete EC2 credential”.
|
||||
This rule determines who can use the Identity API "delete EC2 credential".
|
||||
Here, boolean operators and parentheses combine three simpler rules.
|
||||
<code>admin_required</code> and <code>owner</code> are the same aliases as in the
|
||||
previous example. <code>user_id:%(target.credential.user_id)s</code> compares the
|
||||
API user with the user ID of the credential object associated with the target.</para>
|
||||
<literal>admin_required</literal> and <literal>owner</literal> are the same aliases as in the
|
||||
previous example. <literal>user_id:%(target.credential.user_id)s</literal> compares the
|
||||
API user with the user ID of the credential object associated with the target.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
@ -126,7 +158,7 @@
|
||||
<title>Syntax</title>
|
||||
|
||||
<para>A <filename>policy.json</filename> file consists of policies and aliases of the
|
||||
form <code>target:rule</code> or <code>alias:definition</code>, separated by commas
|
||||
form <literal>target:rule</literal> or <literal>alias:definition</literal>, separated by commas
|
||||
and enclosed in curly braces:
|
||||
|
||||
<programlisting language="json"> {
|
||||
@ -136,21 +168,21 @@
|
||||
"target 1" : "rule 1",
|
||||
"target 2" : "rule 2",
|
||||
....
|
||||
}
|
||||
</programlisting>
|
||||
}</programlisting>
|
||||
|
||||
</para>
|
||||
<para>Targets are APIs and are written <code>"service:API"</code> or simply
|
||||
<code>"API"</code>. For example, <code>"compute:create"</code> or
|
||||
<code>"add_image"</code>.</para>
|
||||
|
||||
<para>Targets are APIs and are written <literal>"service:API"</literal> or simply
|
||||
<literal>"API"</literal>. For example, <literal>"compute:create"</literal> or
|
||||
<literal>"add_image"</literal>.</para>
|
||||
|
||||
<para>Rules determine whether the API call is allowed.</para>
|
||||
<para>Rules can be:
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para>always true. The action is always permitted. This can be written as
|
||||
<code>""</code> (empty string), <code>[]</code>, or <code>"@"</code>.</para></listitem>
|
||||
<listitem><para>always false. The action is never permitted. Written as <code>"!"</code>.</para></listitem>
|
||||
<literal>""</literal> (empty string), <literal>[]</literal>, or <literal>"@"</literal>.</para></listitem>
|
||||
<listitem><para>always false. The action is never permitted. Written as <literal>"!"</literal>.</para></listitem>
|
||||
<listitem><para>a special check</para></listitem>
|
||||
<listitem><para>a comparison of two values</para></listitem>
|
||||
<listitem><para>boolean expressions based on simpler rules</para></listitem>
|
||||
@ -160,11 +192,11 @@
|
||||
<para>Special checks are
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para><code><role>:<role name></code>, a test whether the API credentials
|
||||
<listitem><para><literal><role>:<role name></literal>, a test whether the API credentials
|
||||
contain this role.</para></listitem>
|
||||
<listitem><para><code><rule>:<rule name></code>,
|
||||
<listitem><para><literal><rule>:<rule name></literal>,
|
||||
the definition of an alias.</para></listitem>
|
||||
<listitem><para><code>http:<target URL></code>,
|
||||
<listitem><para><literal>http:<target URL></literal>,
|
||||
which delegates the check to a remote server.
|
||||
The API is authorized when the server returns True.</para></listitem>
|
||||
</itemizedlist>
|
||||
@ -180,24 +212,27 @@
|
||||
<para>Possible values are
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para>constants: Strings, numbers, <code>true</code>, <code>false</code></para></listitem>
|
||||
<listitem><para>constants: Strings, numbers, <literal>true</literal>, <literal>false</literal></para></listitem>
|
||||
<listitem><para>API attributes</para></listitem>
|
||||
<listitem><para>target object attributes</para></listitem>
|
||||
<listitem><para>the flag <code>is_admin</code></para></listitem>
|
||||
<listitem><para>the flag <literal>is_admin</literal></para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para>API attributes can be <code>project_id</code>, <code>user_id</code> or
|
||||
<code>domain_id</code>.</para>
|
||||
<para>API attributes can be <literal>project_id</literal>, <literal>user_id</literal> or
|
||||
<literal>domain_id</literal>.</para>
|
||||
|
||||
<para>Target object attributes are fields from the object description in the database.
|
||||
For example in the case of the <code>"compute:start"</code> API, the object is the
|
||||
For example in the case of the <literal>"compute:start"</literal> API, the object is the
|
||||
instance to be started. The policy for starting instances could use the
|
||||
<code>%(project_id)s</code>attribute, that is the project that owns the instance.
|
||||
<literal>%(project_id)s</literal>attribute, that is the project that owns the instance.
|
||||
The trailing s indicates this is a string.</para>
|
||||
|
||||
<para><code>is_admin</code> tells whether the API user is an administrator,
|
||||
no matter if the user has the admin role or not.</para>
|
||||
<para><literal>is_admin</literal> indicates that administrative privileges
|
||||
are granted via the admin token mechanism (the <parameter>--os-token</parameter>
|
||||
option of the <command>keystone</command> command).
|
||||
The admin token allows initialisation of the identity database before the admin
|
||||
role exists.</para>
|
||||
|
||||
<para>The alias construct exists for convenience. An alias is short name for a
|
||||
complex or hard to understand rule.
|
||||
@ -205,7 +240,7 @@
|
||||
|
||||
<programlisting language="json">alias name : alias definition</programlisting>
|
||||
|
||||
Once an alias is defined, use the <code>rule</code> keyword to use it in a policy rule.</para>
|
||||
Once an alias is defined, use the <literal>rule</literal> keyword to use it in a policy rule.</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user