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