candlepin/candlepin — pull request #444 by dgoodwin (2013-11-28 13:46:05+00:00)
Title: Update auth system to allow "my system" administrators

Overall goal is to allow user accounts which have permissions to manage only systems they registered (as based on the username stored during registration). Additionally we need to support this, plus read-only access to the org, where the user can also see other systems but cannot modify them.

This required extensive changes to the auth system to allow more fine grained control. The hacky READ_POOLS and READ_SUBSCRIPTIONS access level is replaced with the concept of a sub-resource, so we can verify access to entities and also specify a sub-resource. i.e. I can grant a permission for an Owner, sub-resource Pools, access level READ_ONLY to let consumers read pools in an org, but not necessarily browse other systems in the org.

The system administrator permission introduced a new requirement where we only want to see certain consumers in a GET /owner/{key}/consumers, those which match my username. To accomplish this I added the ability for permissions to specify hibernate criteria restrictions to be added to the query before it is run. This has the added benefit of letting pagination continue to work. However the query filters add a lot of complexity where certain permissions can hide things from other permissions. To solve this, the permission filters are OR'd together, and the end result is that in general it is a good idea for permissions to include filters which show exactly what we expect that permission to be allowed to see. OwnerPermission is the most likely place where this will surface.

The dev/QE permissions system was expanded to allow us to store more than just one type of permission in our db, previously we could only store OwnerPermission which would leave us unable to actually test this new system admin role. Instead OwnerPermission became a non-persistent java class, and a PermissionBlueprint was added which can be associated with a role and stored in our db. This contains just enough information for the PermissionFactory to build the actual java class we want.

The trusted auth system was enhanced so a header can be specified which results in Candlepin calling back to the user service to actually ask for the permissions to add to the principal. (previously it would only create principals with full access)

Falling out of the use of filters, we will usually see a 404 not found when asking for access to something the principal has no access to. This reveals less information about what actually exists and prevents making API calls to gather information about what is out there. 403 is still returned in some situations where we can see a resource, we just can't perform the action we're trying to perform.

The filters can be used via AbstractHibernateCurator.createSecureCriteria(). When looking up specific objects by ID there are two methods, one secure, one not. The unsecured one is still required as sometimes we must perform actions the principal technically cannot do. (i.e. a virt_limit unbind means a pool needs to get deleted) When looking up by ID over the REST API you should see a 404 when you do not have permission. Further down the stack we tend to use the insecure method of lookup by ID instead. (See AuthInterceptor EntityStore implementations for where this happens.)

Fixed an issue where the Access level was stored in the db as a positional integer, so code changes could change the meaning of what was stored.

Altered the pool deletion code and removed some strange things we were doing to deal with existence of duplicate attributes. This was a very old problem which does not seem to exist any more. (tested this myself, and also note that we were not doing the strange things for derived product attributes, and no problems have surfaced that we're aware of) The strange code was causing hibernate errors when deleting a pool if we looked up the object with a query rather than a session.get().