Identity trust rbac tests

Add identity trust rbac tests corresponding to the policy actions
in [0].

Most of the policy actions in [0] have a rule of '' (empty string),
meaning any role can perform the action. However, the
"identity:create_trust" policy action has a rule of
base.RULE_TRUST_OWNER which translates to:

  user_id:%(trust.trustor_user_id)s [1].

This is a rather unique rule, one that is not dependent on the
current user's user_id, project_id or even role. Rather, this
rule translates to: "Does the current user's user_id match
the user_id of the trustor creating a trust with a trustee?"

As should be expected, "trust.trustor_user_id" can only be
dynamically calculated at runtime, rather than immediately
retrieved from a tempest credential variable, as is the case
with user_id and project_id.

Hence, this patch not only 1) creates trust rbac tests but 2)
enhances the framework, particularly the rbac_rule_validation
decorator, as well as the rbac_policy_parser framework, to
handle additional target data that must be passed to
oslo-policy-checker in order for proper authorization
determination.

The "target" parameter in oslo.policy is a dictionary that
contains "As much information about the object being
operated on as possible" [2]. Accordingly, the
rbac_rule_validation decorator has been enhanced with a new
param called `extra_target_data` that is a dictionary
containing key-value pairs of dynamically calculated
data needed by oslo.policy to correctly determine whether
the "target" has authorization to perform a policy action.

For example,

    extra_target_data={
        "trust.trustor_user_id": "os.auth_provider.credentials.user_id"
    })

means that trust.trustor_user_id equals the primary credential's
user_id. So, if a trustor's user_id equals the primary credential's
user_id, then the policy parser will return True for `is_allowed`.
However, if a trustor's user_id doesn'tequal to the primary credential's
user_id, but rather the alt credential's user_id, say, then `is_allowed`
returns False.

Thus, the only way to do negative testing with test_trusts_rbac is
to explicitly create a negative test, as described in the above
paragraph, which is what this patch does. Normally, negative testing
is baked in, dependent on the `rbac_test_role`, but with more
complicated policy enforcement as described above, this is not
possible.

While it is possible to create a new CONF value called trustor_user_id,
it would require using pre-provisioned credentials, which is something
Patrole doesn't explicitly use.

[0] https://github.com/openstack/keystone/blob/master/keystone/common/policies/trust.py
[1] https://github.com/openstack/keystone/blob/master/keystone/common/policies/base.py
[2] https://docs.openstack.org/developer/oslo.policy/api/oslo_policy.html

Depends-On: Ib82e8b8a0d6c8587fb0b1ce415e751c3ebc3c2f9
Change-Id: I5c00fdb345556066343bdaeb5f008d639a94bc4b
diff --git a/patrole_tempest_plugin/rbac_policy_parser.py b/patrole_tempest_plugin/rbac_policy_parser.py
index 38bed7c..94aa2c7 100644
--- a/patrole_tempest_plugin/rbac_policy_parser.py
+++ b/patrole_tempest_plugin/rbac_policy_parser.py
@@ -40,7 +40,8 @@
     each role, whether a given rule is allowed using oslo policy.
     """
 
-    def __init__(self, tenant_id, user_id, service=None, path=None):
+    def __init__(self, project_id, user_id, service=None, path=None,
+                 extra_target_data={}):
         """Initialization of Rbac Policy Parser.
 
         Parses a policy file to create a dictionary, mapping policy actions to
@@ -57,7 +58,7 @@
         the custom policy file over the default policy implementation is
         prioritized.
 
-        :param tenant_id: type uuid
+        :param project_id: type uuid
         :param user_id: type uuid
         :param service: type string
         :param path: type string
@@ -78,8 +79,9 @@
         self.path = path or os.path.join('/etc', service, 'policy.json')
         self.rules = policy.Rules.load(self._get_policy_data(service),
                                        'default')
-        self.tenant_id = tenant_id
+        self.project_id = project_id
         self.user_id = user_id
+        self.extra_target_data = extra_target_data
 
     def allowed(self, rule_name, role):
         is_admin_context = self._is_admin_context(role)
@@ -165,8 +167,8 @@
                         "name": role
                     }
                 ],
-                "project_id": self.tenant_id,
-                "tenant_id": self.tenant_id,
+                "project_id": self.project_id,
+                "tenant_id": self.project_id,
                 "user_id": self.user_id
             }
         }
@@ -200,6 +202,8 @@
                   "tenant_id": access_data['project_id'],
                   "network:tenant_id": access_data['project_id'],
                   "user_id": access_data['user_id']}
+        if self.extra_target_data:
+            target.update(self.extra_target_data)
 
         result = self._try_rule(apply_rule, target, access_data, o)
         return result