Files
ansible-collections-openstack/plugins/modules/neutron_rbac_policies_info.py
Jakob Meng e4be201f20 Properly documented openstacksdk version requirements
With "extends_documentation_fragment: ['openstack.cloud.openstack']"
it is not necessary to list required Python libraries in section
'requirements' of DOCUMENTATION docstring in modules. Ansible will
merge requirements from doc fragments and DOCUMENTATION docstring
which previously resulted in duplicates such as in server module [0]:

* openstacksdk
* openstacksdk >= 0.36, < 0.99.0
* python >= 3.6

When removing the 'requirements' section from server module, then
Ansible will list openstacksdk once only:

* openstacksdk >= 0.36, < 0.99.0
* python >= 3.6

To see what documentation Ansible will produce for server module run:

  ansible-doc --type module openstack.cloud.server

[0] https://docs.ansible.com/ansible/latest/collections/openstack/\
    cloud/server_module.html

Change-Id: Ia53c2c34436c7a72080602f5699e82d20f677b8b
2023-01-16 13:52:45 +01:00

237 lines
8.3 KiB
Python

#!/usr/bin/python
# coding: utf-8 -*-
# Copyright: Ansible Project
# (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.
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.
options:
policy_id:
description:
- The RBAC policy ID
- If provided, all other filters are ignored
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)
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)
choices: ['network', 'security_group', 'qos_policy']
type: str
target_project_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)
type: str
project:
description:
- Filters the RBAC rules based on the project name
- Logically AND'ed with other filters
type: str
action:
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']
type: str
extends_documentation_fragment:
- openstack.cloud.openstack
'''
EXAMPLES = r'''
# Gather all rbac policies for a project
- name: Get all rbac policies for {{ project }}
openstack.cloud.neutron_rbac_policies_info:
project_id: "{{ project.id }}"
'''
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
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
type: str
sample: "access_as_shared"
id:
description:
- The ID of the RBAC rule/policy
type: str
sample: "4154ce0c-71a7-4d87-a905-09762098ddb9"
name:
description:
- 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
}
}
'''
import re
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
class NeutronRbacPoliciesInfo(OpenStackModule):
argument_spec = dict(
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.
)
module_kwargs = dict(
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')
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)))
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.')
filtered_policies = self._get_rbac_policies()
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)
self.exit_json(policies=filtered_policies, changed=False)
def main():
module = NeutronRbacPoliciesInfo()
module()
if __name__ == '__main__':
main()