updates in permission handling

Horacio Duran horacio.duran at canonical.com
Wed Aug 17 01:53:55 UTC 2016


As of 02c2b10067bbe2169c2b7a7cfb88c66f9bc69700 in master, there are new
permission options available.

The current permissions, formerly known as **acls** and used to "**share
models**" allow controller administrators to give both internal and
external users different permissions in models and controllers.

=============
What changed?
=============

In the CLI.
===========

Formerly you could create a user and "share" a model with a level of
permission:
  - read
  - write (to all effects was equivalent to admin)
  - admin

all could be done with one command:

``juju add-user <username> [--acls="level"] [models...]``


or in two commands:

``juju add-user <username>``

``juju grant --models=one,two,... --acl="level"``

Currently the user creation command allows only for the creation of the
user, and permissions, now being more extensive than a simple attribute of
the model, are granted separately.

For granting permissions
************************
A simplified grant command is now available:

Permissions can be granted to a user in multiple models with the following
syntax:

``juju grant <username> <permission> [model1 model2 ... modelN]``

**If no model is provided, the command will try to set the permission at a
controller level.**

* For Models , the available permissions are:
 - read (loosely, gives the ability to query the model data, ie juju status)
 - write (gives the ability to modify the world at a model level)
 - admin (gives the ability to perform meta actions)
permissions are cumulative so, each one gives the previous.

* For Controllers, the available permissions are:
 - login (default for all users unless explicitly revoked)
 - addmodel (the user can add models to the controller)
 - superuser (the user is controller administrator, default for the
controller owner)
as with model permissions, they are cumulative.

For revoking
************
the command is similar:

``juju revoke <username> <permission> [model1 model2 ... modelN]``

Revoking a level will leave the user with the previous one or none if the
level is **read** or **login**.

In the API Server
=================

Previously, permission checking was done by a set of rules on the method
finder (in *apiserver/client_auth_root.go*)

This was not in accord with the original intent of the architecture, which
included an *authorizer* in the facade instances to do the permission
checking.

Authorizer gained a **HasPermission** method which has the following
signature:

``HasPermission(level, object) (bool, error)``

Which returns whether the logged in user has that level of permission on
the passed object, currently the passed object can either be a
*names.ControllerTag* or a *names.ModelTag* and the level one of the
aforementioned, which are defined as  *description.Access* constants in
*core/description/access.go*.

There is an additional **UserHasPermission** that has an extra user
argument, that takes a *names.UserTag* in case you need to add the level
for a user other than the one logged in.

``UserHasPermission(user, level, object) (bool, error)``

In most facades there are now convenience methods (mostly called
checkCanXXXX that err if the logged in user cannot perform said action)
that are now called in the facade methods before anything is done to ensure
the user can perform such action or return *common.ErrPerm*.

In the tests.
=============

Implementations of **fakeAuthorizer** became a bit smarter and can now
return true/false when their **HasPermission** is called depending on the
name of the user and/or the AdminTag parameter.

Tests have been fixed accordingly to assume the user running them has the
right permissions since that was the intent of the tests author but you are
encouraged to review your facade method tests and add various permission
cases where such paths are not explored.

In the future.
==============

Facade Methods
**************
To ensure security and consistency, new facade methods should always begin
with a call to **HasPermission** (if any level of permission is required)
otherwise the default permission for a logged in user will be the minimum
expected, please try to be explicit with the level requirement to be future
proof.

If you can add what kind of user the facade method is intended for in the
method doc it can help a lot in debugging if there is any permission issue.

Tests
*****

Future tests should now explore different permission path, a minimum
acceptable should be checking for at least the expected accepted and one
expected not accepted permission level.

Missing Tests
*************

Since now all facade methods have an extra dimension, some new paths might
be untested, you are encouraged to add said paths should you stumble upon
it while doing nearby work.

The review checklist.
*********************

New items should be added to the checklist for cases where the reviewed
code is a facade.

* Make sure there is a permission checking at the top.
* Make sure the doc mentions the target user.
* Make sure the tests for the facade explore all required permission paths.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.ubuntu.com/archives/juju-dev/attachments/20160816/00d5001d/attachment-0001.html>


More information about the Juju-dev mailing list