RequirementsAuthority multi role support enhancement

This patchset eliminates different behaviour between
policy_authority and requirements_authority.

Problem description:

`rbac_test_roles = [member,]`

Policy authority:

`update_port: role:member and role:viewer`

Results in 403/False (we are member but not viewer).

Requirements authority:

```
req_auth:
    update_port:
        - member
        - viewer
```

Results in 200/True (member in update_port list).

Proposed solution:

Change requirements_authority file sytax to support
comma separated roles to be considered as logical and.

Depends-On: https://review.openstack.org/#/c/606110/
Change-Id: I2e2a4a2020f5e85af15f1836d69386bc91a2d2ec
Co-Authored-By: Felipe Monteiro <felipe.monteiro@att.com>
diff --git a/patrole_tempest_plugin/requirements_authority.py b/patrole_tempest_plugin/requirements_authority.py
index 57caf79..4697c3b 100644
--- a/patrole_tempest_plugin/requirements_authority.py
+++ b/patrole_tempest_plugin/requirements_authority.py
@@ -12,6 +12,7 @@
 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 #    License for the specific language governing permissions and limitations
 #    under the License.
+import copy
 import yaml
 
 from oslo_log import log as logging
@@ -50,7 +51,7 @@
             <service_foo>:
               <api_action_a>:
                 - <allowed_role_1>
-                - <allowed_role_2>
+                - <allowed_role_2>,<allowed_role_3>
                 - <allowed_role_3>
               <api_action_b>:
                 - <allowed_role_2>
@@ -67,7 +68,16 @@
         try:
             for section in RequirementsParser.Inner._rbac_map:
                 if component in section:
-                    return section[component]
+                    rules = copy.copy(section[component])
+
+                    for rule in rules:
+                        rules[rule] = [
+                            roles.split(',') for roles in rules[rule]]
+
+                        for i, role_pack in enumerate(rules[rule]):
+                            rules[rule][i] = [r.strip() for r in role_pack]
+
+                    return rules
         except yaml.parser.ParserError:
             LOG.error("Error while parsing the requirements YAML file. Did "
                       "you pass a valid component name from the test case?")
@@ -115,8 +125,24 @@
                 "empty. Ensure the requirements YAML file is correctly "
                 "formatted.")
         try:
-            _api = self.roles_dict[rule_name]
-            return all(role in _api for role in roles)
+            requirement_roles = self.roles_dict[rule_name]
+
+            for role_reqs in requirement_roles:
+                required_roles = [
+                    role for role in role_reqs if not role.startswith("!")]
+                forbidden_roles = [
+                    role[1:] for role in role_reqs if role.startswith("!")]
+
+                # User must have all required roles
+                required_passed = all([r in roles for r in required_roles])
+                # User must not have any forbidden roles
+                forbidden_passed = all([r not in forbidden_roles
+                                        for r in roles])
+
+                if required_passed and forbidden_passed:
+                    return True
+
+            return False
         except KeyError:
             raise KeyError("'%s' API is not defined in the requirements YAML "
                            "file" % rule_name)