Refactored neutron_rbac_polic{ies_info,y} modules

Change-Id: I1cd37096834d4159b5fa46719f5c479cb2bc29a9
This commit is contained in:
Jakob Meng
2022-11-10 19:21:08 +01:00
parent daf79de37e
commit 0f37ed795b
6 changed files with 356 additions and 471 deletions

View File

@@ -5,61 +5,57 @@
# (c) 2021, Ashraf Hasson <ahasson@redhat.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r'''
---
module: neutron_rbac_policies_info
short_description: Fetch Neutron policies.
short_description: Fetch Neutron RBAC policies.
author: OpenStack Ansible SIG
description:
- Get RBAC policies against a network, security group or a QoS Policy for one or more projects.
- If a C(policy_id) was not provided, this module will attempt to fetch all available policies.
- Accepts same arguments as OpenStackSDK network proxy C(find_rbac_policy) and C(rbac_policies) functions which are ultimately passed over to C(RBACPolicy)
- All parameters passed in to this module act as a filter for when no C(policy_id) was provided, otherwise they're ignored.
- Returns None if no matching policy was found as opposed to failing.
- Fetch RBAC policies against a network, security group or a QoS Policy for
one or more projects.
options:
policy_id:
action:
description:
- The RBAC policy ID
- If provided, all other filters are ignored
- Action for the RBAC policy.
- Can be either of the following options C(access_as_shared) or
C(access_as_external).
- Logically AND'ed with other filters.
choices: ['access_as_shared', 'access_as_external']
type: str
object_id:
description:
- The object ID (the subject of the policy) to which the RBAC rules applies
- This would be the ID of a network, security group or a qos policy
- Mutually exclusive with the C(object_type)
- The object ID (the subject of the policy) to which the RBAC rules
applies.
- This is an ID of a network, security group or a qos policy.
- Mutually exclusive with the C(object_type).
type: str
object_type:
description:
- Can be one of the following object types C(network), C(security_group) or C(qos_policy)
- Mutually exclusive with the C(object_id)
- Type of the object that this RBAC policy affects.
- Can be one of the following object types C(network), C(security_group)
or C(qos_policy).
- Mutually exclusive with the C(object_id).
choices: ['network', 'security_group', 'qos_policy']
type: str
target_project_id:
policy_id:
description:
- Filters the RBAC rules based on the target project id
- Logically AND'ed with other filters
- Mutually exclusive with C(project_id)
type: str
project_id:
description:
- Filters the RBAC rules based on the project id to which the object belongs to
- Logically AND'ed with other filters
- Mutually exclusive with C(target_project_id)
- The RBAC policy ID.
- If C(policy_id) is not provided, all available policies will be
fetched.
- If C(policy_id) provided, all other filters are ignored.
type: str
project:
description:
- Filters the RBAC rules based on the project name
- Logically AND'ed with other filters
- ID or name of the project to which C(object_id) belongs to.
- Filters the RBAC rules based on the project name.
- Logically AND'ed with other filters.
type: str
action:
aliases: ['project_id']
target_project_id:
description:
- Can be either of the following options C(access_as_shared) | C(access_as_external)
- Logically AND'ed with other filters
choices: ['access_as_shared', 'access_as_external']
- The ID of the project this RBAC will be enforced.
- Filters the RBAC rules based on the target project id.
- Logically AND'ed with other filters.
type: str
extends_documentation_fragment:
@@ -67,40 +63,18 @@ extends_documentation_fragment:
'''
EXAMPLES = r'''
# Gather all rbac policies for a project
- name: Get all rbac policies for {{ project }}
- name: Get all rbac policies for a project
openstack.cloud.neutron_rbac_policies_info:
project_id: "{{ project.id }}"
project: one_project
'''
RETURN = r'''
# return value can either be plural or signular depending on what was passed in as parameters
policies:
description:
- List of rbac policies, this could also be returned as a singular element, i.e., 'policy'
type: complex
rbac_policies:
description: List of Neutron RBAC policies.
type: list
elements: dict
returned: always
contains:
object_id:
description:
- The UUID of the object to which the RBAC rules apply
type: str
sample: "7422172b-2961-475c-ac68-bd0f2a9960ad"
target_project_id:
description:
- The UUID of the target project
type: str
sample: "c201a689c016435c8037977166f77368"
project_id:
description:
- The UUID of the project to which access is granted
type: str
sample: "84b8774d595b41e89f3dfaa1fd76932c"
object_type:
description:
- The object type to which the RBACs apply
type: str
sample: "network"
action:
description:
- The access model specified by the RBAC rules
@@ -116,120 +90,96 @@ policies:
- The name of the RBAC rule; usually null
type: str
sample: null
location:
description:
- A dictionary of the project details to which access is granted
type: dict
sample: >-
{
"cloud": "devstack",
"region_name": "",
"zone": null,
"project": {
"id": "84b8774d595b41e89f3dfaa1fd76932c",
"name": null,
"domain_id": null,
"domain_name": null
}
}
object_id:
description:
- The UUID of the object to which the RBAC rules apply
type: str
sample: "7422172b-2961-475c-ac68-bd0f2a9960ad"
object_type:
description:
- The object type to which the RBACs apply
type: str
sample: "network"
project_id:
description:
- The UUID of the project to which access is granted
type: str
sample: "84b8774d595b41e89f3dfaa1fd76932c"
target_project_id:
description:
- The UUID of the target project
type: str
sample: "c201a689c016435c8037977166f77368"
tenant_id:
description:
- The UUID of the project to which access is granted. Deprecated.
type: str
sample: "84b8774d595b41e89f3dfaa1fd76932c"
policies:
description: Same as C(rbac_policies), kept for backward compatibility.
returned: always
type: list
elements: dict
'''
import re
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
class NeutronRbacPoliciesInfo(OpenStackModule):
class NeutronRBACPoliciesInfo(OpenStackModule):
argument_spec = dict(
action=dict(choices=['access_as_external', 'access_as_shared']),
object_id=dict(),
object_type=dict(choices=['security_group', 'qos_policy', 'network']),
policy_id=dict(),
object_id=dict(), # ID of the object that this RBAC policy affects.
object_type=dict(choices=['security_group', 'qos_policy', 'network']), # Type of the object that this RBAC policy affects.
target_project_id=dict(), # The ID of the project this RBAC will be enforced.
project_id=dict(), # The owner project ID.
project=dict(),
action=dict(choices=['access_as_external', 'access_as_shared']), # Action for the RBAC policy.
project=dict(aliases=['project_id']),
target_project_id=dict(),
)
module_kwargs = dict(
mutually_exclusive=[
('object_id', 'object_type'),
],
supports_check_mode=True,
)
def _filter_policies_by(self, policies, key, value):
filtered = []
regexp = re.compile(r"location\.project\.([A-Za-z]+)")
if regexp.match(key):
attribute = key.split('.')[-1]
for p in policies:
if p['location']['project'][attribute] == value:
filtered.append(p)
else:
for p in policies:
if getattr(p, key) == value:
filtered.append(p)
return filtered
def _get_rbac_policies(self):
object_type = self.params.get('object_type')
project_id = self.params.get('project_id')
action = self.params.get('action')
search_attributes = {}
if object_type is not None:
search_attributes['object_type'] = object_type
if project_id is not None:
search_attributes['project_id'] = project_id
if action is not None:
search_attributes['action'] = action
try:
policies = []
generator = self.conn.network.rbac_policies(**search_attributes)
for p in generator:
policies.append(p)
except self.sdk.exceptions.OpenStackCloudException as ex:
self.fail_json(msg='Failed to get RBAC policies: {0}'.format(str(ex)))
return policies
def run(self):
policy_id = self.params.get('policy_id')
object_id = self.params.get('object_id')
object_type = self.params.get('object_type')
project_id = self.params.get('project_id')
project = self.params.get('project')
target_project_id = self.params.get('target_project_id')
project_name_or_id = self.params['project']
project = None
if project_name_or_id is not None:
project = self.conn.identity.find_project(project_name_or_id)
if not project:
self.exit_json(changed=False, rbac_policies=[], policies=[])
if self.ansible.check_mode:
self.exit_json(changed=False)
if policy_id is not None:
try:
policy = self.conn.network.get_rbac_policy(policy_id)
self.exit_json(changed=False, policy=policy)
except self.sdk.exceptions.ResourceNotFound:
self.exit_json(changed=False, policy=None)
except self.sdk.exceptions.OpenStackCloudException as ex:
self.fail_json(msg='Failed to get RBAC policy: {0}'.format(str(ex)))
policy_id = self.params['policy_id']
if policy_id:
policy = self.conn.network.find_rbac_policy(policy_id)
policies = [policy] if policy else []
else:
if object_id is not None and object_type is not None:
self.fail_json(msg='object_id and object_type are mutually exclusive, please specify one of the two.')
if project_id is not None and target_project_id is not None:
self.fail_json(msg='project_id and target_project_id are mutually exclusive, please specify one of the two.')
kwargs = dict((k, self.params[k])
for k in ['action', 'object_type']
if self.params[k] is not None)
filtered_policies = self._get_rbac_policies()
if project:
kwargs['project_id'] = project.id
if project is not None:
filtered_policies = self._filter_policies_by(filtered_policies, 'location.project.name', project)
if object_id is not None:
filtered_policies = self._filter_policies_by(filtered_policies, 'object_id', object_id)
if target_project_id is not None:
filtered_policies = self._filter_policies_by(filtered_policies, 'target_project_id', target_project_id)
policies = list(self.conn.network.rbac_policies(**kwargs))
self.exit_json(policies=filtered_policies, changed=False)
for k in ['object_id', 'target_project_id']:
if self.params[k] is not None:
policies = [p for p in policies if p[k] == self.params[k]]
if project:
policies = [p for p in policies
if p['location']['project']['id'] == project.id]
policies = [p.to_dict(computed=False) for p in policies]
self.exit_json(changed=False,
rbac_policies=policies,
policies=policies)
def main():
module = NeutronRbacPoliciesInfo()
module = NeutronRBACPoliciesInfo()
module()