Refactored neutron_rbac_polic{ies_info,y} modules
Change-Id: I1cd37096834d4159b5fa46719f5c479cb2bc29a9
This commit is contained in:
parent
daf79de37e
commit
0f37ed795b
73
.zuul.yaml
73
.zuul.yaml
@ -60,65 +60,6 @@
|
|||||||
description: |
|
description: |
|
||||||
Run openstack collections functional tests against a master devstack
|
Run openstack collections functional tests against a master devstack
|
||||||
using master of openstacksdk with latest ansible release
|
using master of openstacksdk with latest ansible release
|
||||||
vars:
|
|
||||||
# TODO: Remove tox_extra_args once all ci roles pass
|
|
||||||
tox_extra_args: &skip_broken_ci_roles >-
|
|
||||||
address_scope
|
|
||||||
auth
|
|
||||||
catalog_service
|
|
||||||
compute_flavor
|
|
||||||
compute_flavor_access
|
|
||||||
config
|
|
||||||
dns
|
|
||||||
dns_zone_info
|
|
||||||
endpoint
|
|
||||||
federation_mapping
|
|
||||||
floating_ip
|
|
||||||
host_aggregate
|
|
||||||
identity_domain_info
|
|
||||||
identity_group
|
|
||||||
identity_group_info
|
|
||||||
identity_user
|
|
||||||
identity_user_info
|
|
||||||
identity_role
|
|
||||||
identity_role_info
|
|
||||||
image
|
|
||||||
image_info
|
|
||||||
keypair
|
|
||||||
keystone_domain
|
|
||||||
keystone_federation_protocol
|
|
||||||
keystone_idp
|
|
||||||
logging
|
|
||||||
loadbalancer
|
|
||||||
network
|
|
||||||
nova_services
|
|
||||||
object
|
|
||||||
object_container
|
|
||||||
port
|
|
||||||
project
|
|
||||||
project_info
|
|
||||||
quota
|
|
||||||
recordset
|
|
||||||
role_assignment
|
|
||||||
router
|
|
||||||
security_group
|
|
||||||
security_group_rule
|
|
||||||
server
|
|
||||||
server_group
|
|
||||||
server_metadata
|
|
||||||
server_volume
|
|
||||||
stack
|
|
||||||
subnet
|
|
||||||
subnet_pool
|
|
||||||
user
|
|
||||||
user_group
|
|
||||||
user_role
|
|
||||||
volume
|
|
||||||
volume_backup
|
|
||||||
volume_snapshot
|
|
||||||
volume_type_access
|
|
||||||
# failing tags
|
|
||||||
# neutron_rbac
|
|
||||||
|
|
||||||
- job:
|
- job:
|
||||||
name: ansible-collections-openstack-functional-devstack-octavia-base
|
name: ansible-collections-openstack-functional-devstack-octavia-base
|
||||||
@ -166,9 +107,6 @@
|
|||||||
Run openstack collections functional tests against a master devstack
|
Run openstack collections functional tests against a master devstack
|
||||||
with Octavia plugin enabled, using latest releases of openstacksdk
|
with Octavia plugin enabled, using latest releases of openstacksdk
|
||||||
and latest ansible release. Run it only on Load Balancer changes.
|
and latest ansible release. Run it only on Load Balancer changes.
|
||||||
vars:
|
|
||||||
# TODO: Remove tox_extra_args once all ci roles pass
|
|
||||||
tox_extra_args: *skip_broken_ci_roles
|
|
||||||
|
|
||||||
- job:
|
- job:
|
||||||
name: ansible-collections-openstack-functional-devstack-releases
|
name: ansible-collections-openstack-functional-devstack-releases
|
||||||
@ -179,8 +117,6 @@
|
|||||||
using latest releases of openstacksdk and latest ansible release
|
using latest releases of openstacksdk and latest ansible release
|
||||||
vars:
|
vars:
|
||||||
tox_constraints_file: '{{ ansible_user_dir }}/{{ zuul.project.src_dir }}/tests/constraints-openstacksdk-1.x.x.txt'
|
tox_constraints_file: '{{ ansible_user_dir }}/{{ zuul.project.src_dir }}/tests/constraints-openstacksdk-1.x.x.txt'
|
||||||
# TODO: Remove tox_extra_args once all ci roles pass
|
|
||||||
tox_extra_args: *skip_broken_ci_roles
|
|
||||||
tox_install_siblings: false
|
tox_install_siblings: false
|
||||||
|
|
||||||
# Job with Ansible 2.9 for checking backward compatibility
|
# Job with Ansible 2.9 for checking backward compatibility
|
||||||
@ -196,8 +132,6 @@
|
|||||||
override-checkout: stable-2.9
|
override-checkout: stable-2.9
|
||||||
vars:
|
vars:
|
||||||
tox_envlist: ansible-2.9
|
tox_envlist: ansible-2.9
|
||||||
# TODO: Remove tox_extra_args once all ci roles pass
|
|
||||||
tox_extra_args: *skip_broken_ci_roles
|
|
||||||
|
|
||||||
- job:
|
- job:
|
||||||
name: ansible-collections-openstack-functional-devstack-ansible-2.11
|
name: ansible-collections-openstack-functional-devstack-ansible-2.11
|
||||||
@ -211,8 +145,6 @@
|
|||||||
override-checkout: stable-2.11
|
override-checkout: stable-2.11
|
||||||
vars:
|
vars:
|
||||||
tox_envlist: ansible-2.11
|
tox_envlist: ansible-2.11
|
||||||
# TODO: Remove tox_extra_args once all ci roles pass
|
|
||||||
tox_extra_args: *skip_broken_ci_roles
|
|
||||||
|
|
||||||
- job:
|
- job:
|
||||||
name: ansible-collections-openstack-functional-devstack-ansible-2.12
|
name: ansible-collections-openstack-functional-devstack-ansible-2.12
|
||||||
@ -226,8 +158,6 @@
|
|||||||
override-checkout: stable-2.12
|
override-checkout: stable-2.12
|
||||||
vars:
|
vars:
|
||||||
tox_envlist: ansible-2.12
|
tox_envlist: ansible-2.12
|
||||||
# TODO: Remove tox_extra_args once all ci roles pass
|
|
||||||
tox_extra_args: *skip_broken_ci_roles
|
|
||||||
|
|
||||||
- job:
|
- job:
|
||||||
name: ansible-collections-openstack-functional-devstack-ansible-devel
|
name: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||||
@ -242,9 +172,6 @@
|
|||||||
required-projects:
|
required-projects:
|
||||||
- name: github.com/ansible/ansible
|
- name: github.com/ansible/ansible
|
||||||
override-checkout: devel
|
override-checkout: devel
|
||||||
vars:
|
|
||||||
# TODO: Remove tox_extra_args once all ci roles pass
|
|
||||||
tox_extra_args: *skip_broken_ci_roles
|
|
||||||
|
|
||||||
# Linters
|
# Linters
|
||||||
- job:
|
- job:
|
||||||
|
9
ci/roles/neutron_rbac_policy/defaults/main.yml
Normal file
9
ci/roles/neutron_rbac_policy/defaults/main.yml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
expected_fields:
|
||||||
|
- action
|
||||||
|
- id
|
||||||
|
- name
|
||||||
|
- object_id
|
||||||
|
- object_type
|
||||||
|
- project_id
|
||||||
|
- target_project_id
|
||||||
|
- tenant_id
|
@ -1,27 +1,18 @@
|
|||||||
---
|
---
|
||||||
# General run of tests
|
|
||||||
# - Prepare projects/network objects
|
|
||||||
# - Create rbac object
|
|
||||||
# - Get rbac object info
|
|
||||||
# - Verify RBAC object match
|
|
||||||
# - Delete rbac object
|
|
||||||
# - Get rbac object info
|
|
||||||
# - Verify RBAC object deleted
|
|
||||||
|
|
||||||
- name: Create source project
|
- name: Create source project
|
||||||
openstack.cloud.project:
|
openstack.cloud.project:
|
||||||
cloud: "{{ cloud }}"
|
cloud: "{{ cloud }}"
|
||||||
state: present
|
state: present
|
||||||
name: source_project
|
name: ansible_source_project
|
||||||
description: Source project for network RBAC test
|
description: Source project for network RBAC test
|
||||||
domain_id: default
|
domain_id: default
|
||||||
enabled: True
|
enabled: True
|
||||||
register: source_project
|
register: source_project
|
||||||
|
|
||||||
- name: Create network - generic
|
- name: Create network
|
||||||
openstack.cloud.network:
|
openstack.cloud.network:
|
||||||
cloud: "{{ cloud }}"
|
cloud: "{{ cloud }}"
|
||||||
name: "{{ network_name }}"
|
name: "ansible_network"
|
||||||
state: present
|
state: present
|
||||||
project: "{{ source_project.project.id }}"
|
project: "{{ source_project.project.id }}"
|
||||||
shared: false
|
shared: false
|
||||||
@ -32,7 +23,7 @@
|
|||||||
openstack.cloud.project:
|
openstack.cloud.project:
|
||||||
cloud: "{{ cloud }}"
|
cloud: "{{ cloud }}"
|
||||||
state: present
|
state: present
|
||||||
name: ansible_project
|
name: ansible_target_project
|
||||||
description: Target project for network RBAC test
|
description: Target project for network RBAC test
|
||||||
domain_id: default
|
domain_id: default
|
||||||
enabled: True
|
enabled: True
|
||||||
@ -48,38 +39,62 @@
|
|||||||
project_id: "{{ source_project.project.id }}"
|
project_id: "{{ source_project.project.id }}"
|
||||||
register: rbac_policy
|
register: rbac_policy
|
||||||
|
|
||||||
|
- name: Assert return values of neutron_rbac_policy module
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
# allow new fields to be introduced but prevent fields from being removed
|
||||||
|
- expected_fields|difference(rbac_policy.rbac_policy.keys())|length == 0
|
||||||
|
|
||||||
- name: Get all rbac policies for {{ source_project.project.name }} - after creation
|
- name: Get all rbac policies for {{ source_project.project.name }} - after creation
|
||||||
openstack.cloud.neutron_rbac_policies_info:
|
openstack.cloud.neutron_rbac_policies_info:
|
||||||
cloud: "{{ cloud }}"
|
cloud: "{{ cloud }}"
|
||||||
project_id: "{{ source_project.project.id }}"
|
project: "{{ source_project.project.id }}"
|
||||||
register: rbac_policies
|
register: rbac_policies
|
||||||
|
|
||||||
- name: Capture all existing policy IDs
|
- name: Assert return values of neutron_rbac_policy_info module
|
||||||
set_fact:
|
assert:
|
||||||
rbac_policy_ids: "{{ rbac_policies.policies | map(attribute='id') | list }}"
|
that:
|
||||||
|
# allow new fields to be introduced but prevent fields from being removed
|
||||||
|
- expected_fields|difference(rbac_policies.rbac_policies[0].keys())|length == 0
|
||||||
|
|
||||||
- name: Verify policy exists - after creation
|
- name: Verify policy exists - after creation
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- rbac_policy.policy.id in rbac_policy_ids
|
- rbac_policy.rbac_policy.id in
|
||||||
|
( rbac_policies.rbac_policies | map(attribute='id') | list )
|
||||||
|
|
||||||
- name: Delete RBAC policy
|
- name: Delete RBAC policy
|
||||||
openstack.cloud.neutron_rbac_policy:
|
openstack.cloud.neutron_rbac_policy:
|
||||||
cloud: "{{ cloud }}"
|
cloud: "{{ cloud }}"
|
||||||
policy_id: "{{ rbac_policy.policy.id }}"
|
id: "{{ rbac_policy.rbac_policy.id }}"
|
||||||
state: absent
|
state: absent
|
||||||
|
|
||||||
- name: Get all rbac policies for {{ source_project.project.name }} - after deletion
|
- name: Get all rbac policies for {{ source_project.project.name }} - after deletion
|
||||||
openstack.cloud.neutron_rbac_policies_info:
|
openstack.cloud.neutron_rbac_policies_info:
|
||||||
cloud: "{{ cloud }}"
|
cloud: "{{ cloud }}"
|
||||||
project_id: "{{ source_project.project.id }}"
|
project: "{{ source_project.project.id }}"
|
||||||
register: rbac_policies_remaining
|
register: rbac_policies_remaining
|
||||||
|
|
||||||
- name: Capture all remaining policy IDs
|
|
||||||
set_fact:
|
|
||||||
remaining_rbac_policy_ids: "{{ rbac_policies_remaining.policies | map(attribute='id') | list }}"
|
|
||||||
|
|
||||||
- name: Verify policy does not exist - after deletion
|
- name: Verify policy does not exist - after deletion
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- not rbac_policy.policy.id in remaining_rbac_policy_ids
|
- rbac_policy.rbac_policy.id not in
|
||||||
|
( rbac_policies_remaining.rbac_policies | map(attribute='id') | list )
|
||||||
|
|
||||||
|
- name: Delete target project
|
||||||
|
openstack.cloud.project:
|
||||||
|
cloud: "{{ cloud }}"
|
||||||
|
state: absent
|
||||||
|
name: ansible_target_project
|
||||||
|
|
||||||
|
- name: Delete network
|
||||||
|
openstack.cloud.network:
|
||||||
|
cloud: "{{ cloud }}"
|
||||||
|
name: "ansible_network"
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Delete source project
|
||||||
|
openstack.cloud.project:
|
||||||
|
cloud: "{{ cloud }}"
|
||||||
|
state: absent
|
||||||
|
name: ansible_source_project
|
@ -40,10 +40,7 @@
|
|||||||
when: sdk_version is version(0.44, '>=')
|
when: sdk_version is version(0.44, '>=')
|
||||||
- { role: logging, tags: logging }
|
- { role: logging, tags: logging }
|
||||||
- { role: network, tags: network }
|
- { role: network, tags: network }
|
||||||
- role: neutron_rbac
|
- { role: neutron_rbac_policy, tags: neutron_rbac_policy }
|
||||||
tags:
|
|
||||||
- rbac
|
|
||||||
- neutron_rbac
|
|
||||||
- role: nova_services
|
- role: nova_services
|
||||||
tags: nova_services
|
tags: nova_services
|
||||||
when: sdk_version is version(0.44, '>=')
|
when: sdk_version is version(0.44, '>=')
|
||||||
|
@ -5,61 +5,57 @@
|
|||||||
# (c) 2021, Ashraf Hasson <ahasson@redhat.com>
|
# (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)
|
# 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'''
|
DOCUMENTATION = r'''
|
||||||
---
|
---
|
||||||
module: neutron_rbac_policies_info
|
module: neutron_rbac_policies_info
|
||||||
short_description: Fetch Neutron policies.
|
short_description: Fetch Neutron RBAC policies.
|
||||||
author: OpenStack Ansible SIG
|
author: OpenStack Ansible SIG
|
||||||
description:
|
description:
|
||||||
- Get RBAC policies against a network, security group or a QoS Policy for one or more projects.
|
- Fetch RBAC policies against a network, security group or a QoS Policy for
|
||||||
- If a C(policy_id) was not provided, this module will attempt to fetch all available policies.
|
one or more projects.
|
||||||
- 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:
|
options:
|
||||||
policy_id:
|
action:
|
||||||
description:
|
description:
|
||||||
- The RBAC policy ID
|
- Action for the RBAC policy.
|
||||||
- If provided, all other filters are ignored
|
- 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
|
type: str
|
||||||
object_id:
|
object_id:
|
||||||
description:
|
description:
|
||||||
- The object ID (the subject of the policy) to which the RBAC rules applies
|
- The object ID (the subject of the policy) to which the RBAC rules
|
||||||
- This would be the ID of a network, security group or a qos policy
|
applies.
|
||||||
- Mutually exclusive with the C(object_type)
|
- This is an ID of a network, security group or a qos policy.
|
||||||
|
- Mutually exclusive with the C(object_type).
|
||||||
type: str
|
type: str
|
||||||
object_type:
|
object_type:
|
||||||
description:
|
description:
|
||||||
- Can be one of the following object types C(network), C(security_group) or C(qos_policy)
|
- Type of the object that this RBAC policy affects.
|
||||||
- Mutually exclusive with the C(object_id)
|
- 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']
|
choices: ['network', 'security_group', 'qos_policy']
|
||||||
type: str
|
type: str
|
||||||
target_project_id:
|
policy_id:
|
||||||
description:
|
description:
|
||||||
- Filters the RBAC rules based on the target project id
|
- The RBAC policy ID.
|
||||||
- Logically AND'ed with other filters
|
- If C(policy_id) is not provided, all available policies will be
|
||||||
- Mutually exclusive with C(project_id)
|
fetched.
|
||||||
type: str
|
- If C(policy_id) provided, all other filters are ignored.
|
||||||
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
|
type: str
|
||||||
project:
|
project:
|
||||||
description:
|
description:
|
||||||
- Filters the RBAC rules based on the project name
|
- ID or name of the project to which C(object_id) belongs to.
|
||||||
- Logically AND'ed with other filters
|
- Filters the RBAC rules based on the project name.
|
||||||
|
- Logically AND'ed with other filters.
|
||||||
type: str
|
type: str
|
||||||
action:
|
aliases: ['project_id']
|
||||||
|
target_project_id:
|
||||||
description:
|
description:
|
||||||
- Can be either of the following options C(access_as_shared) | C(access_as_external)
|
- The ID of the project this RBAC will be enforced.
|
||||||
- Logically AND'ed with other filters
|
- Filters the RBAC rules based on the target project id.
|
||||||
choices: ['access_as_shared', 'access_as_external']
|
- Logically AND'ed with other filters.
|
||||||
type: str
|
type: str
|
||||||
|
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
@ -67,40 +63,18 @@ extends_documentation_fragment:
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
EXAMPLES = r'''
|
EXAMPLES = r'''
|
||||||
# Gather all rbac policies for a project
|
- name: Get all rbac policies for a project
|
||||||
- name: Get all rbac policies for {{ project }}
|
|
||||||
openstack.cloud.neutron_rbac_policies_info:
|
openstack.cloud.neutron_rbac_policies_info:
|
||||||
project_id: "{{ project.id }}"
|
project: one_project
|
||||||
'''
|
'''
|
||||||
|
|
||||||
RETURN = r'''
|
RETURN = r'''
|
||||||
# return value can either be plural or signular depending on what was passed in as parameters
|
rbac_policies:
|
||||||
policies:
|
description: List of Neutron RBAC policies.
|
||||||
description:
|
type: list
|
||||||
- List of rbac policies, this could also be returned as a singular element, i.e., 'policy'
|
elements: dict
|
||||||
type: complex
|
|
||||||
returned: always
|
returned: always
|
||||||
contains:
|
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:
|
action:
|
||||||
description:
|
description:
|
||||||
- The access model specified by the RBAC rules
|
- The access model specified by the RBAC rules
|
||||||
@ -116,120 +90,96 @@ policies:
|
|||||||
- The name of the RBAC rule; usually null
|
- The name of the RBAC rule; usually null
|
||||||
type: str
|
type: str
|
||||||
sample: null
|
sample: null
|
||||||
location:
|
object_id:
|
||||||
description:
|
description:
|
||||||
- A dictionary of the project details to which access is granted
|
- The UUID of the object to which the RBAC rules apply
|
||||||
type: dict
|
type: str
|
||||||
sample: >-
|
sample: "7422172b-2961-475c-ac68-bd0f2a9960ad"
|
||||||
{
|
object_type:
|
||||||
"cloud": "devstack",
|
description:
|
||||||
"region_name": "",
|
- The object type to which the RBACs apply
|
||||||
"zone": null,
|
type: str
|
||||||
"project": {
|
sample: "network"
|
||||||
"id": "84b8774d595b41e89f3dfaa1fd76932c",
|
project_id:
|
||||||
"name": null,
|
description:
|
||||||
"domain_id": null,
|
- The UUID of the project to which access is granted
|
||||||
"domain_name": null
|
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
|
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||||
|
|
||||||
|
|
||||||
class NeutronRbacPoliciesInfo(OpenStackModule):
|
class NeutronRBACPoliciesInfo(OpenStackModule):
|
||||||
argument_spec = dict(
|
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(),
|
policy_id=dict(),
|
||||||
object_id=dict(), # ID of the object that this RBAC policy affects.
|
project=dict(aliases=['project_id']),
|
||||||
object_type=dict(choices=['security_group', 'qos_policy', 'network']), # Type of the object that this RBAC policy affects.
|
target_project_id=dict(),
|
||||||
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(
|
module_kwargs = dict(
|
||||||
|
mutually_exclusive=[
|
||||||
|
('object_id', 'object_type'),
|
||||||
|
],
|
||||||
supports_check_mode=True,
|
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):
|
def run(self):
|
||||||
policy_id = self.params.get('policy_id')
|
project_name_or_id = self.params['project']
|
||||||
object_id = self.params.get('object_id')
|
project = None
|
||||||
object_type = self.params.get('object_type')
|
if project_name_or_id is not None:
|
||||||
project_id = self.params.get('project_id')
|
project = self.conn.identity.find_project(project_name_or_id)
|
||||||
project = self.params.get('project')
|
if not project:
|
||||||
target_project_id = self.params.get('target_project_id')
|
self.exit_json(changed=False, rbac_policies=[], policies=[])
|
||||||
|
|
||||||
if self.ansible.check_mode:
|
policy_id = self.params['policy_id']
|
||||||
self.exit_json(changed=False)
|
if policy_id:
|
||||||
|
policy = self.conn.network.find_rbac_policy(policy_id)
|
||||||
if policy_id is not None:
|
policies = [policy] if policy else []
|
||||||
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:
|
else:
|
||||||
if object_id is not None and object_type is not None:
|
kwargs = dict((k, self.params[k])
|
||||||
self.fail_json(msg='object_id and object_type are mutually exclusive, please specify one of the two.')
|
for k in ['action', 'object_type']
|
||||||
if project_id is not None and target_project_id is not None:
|
if self.params[k] 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:
|
||||||
|
kwargs['project_id'] = project.id
|
||||||
|
|
||||||
if project is not None:
|
policies = list(self.conn.network.rbac_policies(**kwargs))
|
||||||
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)
|
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():
|
def main():
|
||||||
module = NeutronRbacPoliciesInfo()
|
module = NeutronRBACPoliciesInfo()
|
||||||
module()
|
module()
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,50 +8,64 @@
|
|||||||
DOCUMENTATION = r'''
|
DOCUMENTATION = r'''
|
||||||
---
|
---
|
||||||
module: neutron_rbac_policy
|
module: neutron_rbac_policy
|
||||||
short_description: Create or delete a Neutron policy to apply a RBAC rule against an object.
|
short_description: Create or delete a Neutron RBAC policy.
|
||||||
author: OpenStack Ansible SIG
|
author: OpenStack Ansible SIG
|
||||||
description:
|
description:
|
||||||
- Create a policy to apply a RBAC rule against a network, security group or a QoS Policy or update/delete an existing policy.
|
- Create, update or delete a policy to apply a RBAC rule against a network,
|
||||||
- If a C(policy_id) was provided but not found, this module will attempt to create a new policy rather than error out when updating an existing rule.
|
security group or QoS Policy.
|
||||||
- Accepts same arguments as OpenStackSDK network proxy C(find_rbac_policy) and C(rbac_policies) functions which are ultimately passed over to C(RBACPolicy)
|
|
||||||
|
|
||||||
options:
|
options:
|
||||||
policy_id:
|
action:
|
||||||
description:
|
description:
|
||||||
- The RBAC policy ID
|
- Action for the RBAC policy.
|
||||||
- Required when deleting or updating an existing RBAC policy rule, ignored otherwise
|
- Can be either of the following options C(access_as_shared) or
|
||||||
|
C(access_as_external).
|
||||||
|
- Cannot be changed when updating an existing policy.
|
||||||
|
- Required when creating a RBAC policy rule, ignored when deleting a
|
||||||
|
policy.
|
||||||
|
choices: ['access_as_shared', 'access_as_external']
|
||||||
type: str
|
type: str
|
||||||
|
id:
|
||||||
|
description:
|
||||||
|
- The RBAC policy ID.
|
||||||
|
- Required when deleting or updating an existing RBAC policy rule,
|
||||||
|
ignored otherwise.
|
||||||
|
- If a I(id) was provided but a policy with this ID cannot be found,
|
||||||
|
an error will be raised.
|
||||||
|
type: str
|
||||||
|
aliases: ['policy_id']
|
||||||
object_id:
|
object_id:
|
||||||
description:
|
description:
|
||||||
- The object ID (the subject of the policy) to which the RBAC rule applies
|
- The object ID (the subject of the policy) to which the RBAC rule
|
||||||
- Cannot be changed when updating an existing policy
|
applies.
|
||||||
- Required when creating a RBAC policy rule, ignored when deleting a policy
|
- Cannot be changed when updating an existing policy.
|
||||||
|
- Required when creating a RBAC policy rule, ignored when deleting a
|
||||||
|
policy.
|
||||||
type: str
|
type: str
|
||||||
object_type:
|
object_type:
|
||||||
description:
|
description:
|
||||||
- Can be one of the following object types C(network), C(security_group) or C(qos_policy)
|
- Type of the object that this RBAC policy affects.
|
||||||
- Cannot be changed when updating an existing policy
|
- Can be one of the following object types C(network), C(security_group)
|
||||||
- Required when creating a RBAC policy rule, ignored when deleting a policy
|
or C(qos_policy).
|
||||||
|
- Cannot be changed when updating an existing policy.
|
||||||
|
- Required when creating a RBAC policy rule, ignored when deleting a
|
||||||
|
policy.
|
||||||
choices: ['network', 'security_group', 'qos_policy']
|
choices: ['network', 'security_group', 'qos_policy']
|
||||||
type: str
|
type: str
|
||||||
target_project_id:
|
|
||||||
description:
|
|
||||||
- The project to which access to be allowed or revoked/disallowed
|
|
||||||
- Can be specified/changed when updating an existing policy
|
|
||||||
- Required when creating or updating a RBAC policy rule, ignored when deleting a policy
|
|
||||||
type: str
|
|
||||||
project_id:
|
project_id:
|
||||||
description:
|
description:
|
||||||
- The project to which the object_id belongs
|
- The ID of the project to which C(object_id) belongs to.
|
||||||
- Cannot be changed when updating an existing policy
|
- Cannot be changed when updating an existing policy.
|
||||||
- Required when creating a RBAC policy rule, ignored when deleting a policy
|
- Required when creating a RBAC policy rule, ignored when deleting a
|
||||||
|
policy.
|
||||||
type: str
|
type: str
|
||||||
action:
|
target_project_id:
|
||||||
description:
|
description:
|
||||||
- Can be either of the following options C(access_as_shared) | C(access_as_external)
|
- The ID of the project to which access to be allowed or revoked aka
|
||||||
- Cannot be changed when updating an existing policy
|
disallowed.
|
||||||
- Required when creating a RBAC policy rule, ignored when deleting a policy
|
- Required when creating or updating a RBAC policy rule, ignored when
|
||||||
choices: ['access_as_shared', 'access_as_external']
|
deleting a policy.
|
||||||
type: str
|
type: str
|
||||||
state:
|
state:
|
||||||
description:
|
description:
|
||||||
@ -65,54 +79,25 @@ extends_documentation_fragment:
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
EXAMPLES = r'''
|
EXAMPLES = r'''
|
||||||
# Ensure network RBAC policy exists
|
- name: Create or update RBAC policy
|
||||||
- name: Create a new network RBAC policy
|
|
||||||
neutron_rbac_policy:
|
neutron_rbac_policy:
|
||||||
object_id: '7422172b-2961-475c-ac68-bd0f2a9960ad'
|
object_id: '7422172b-2961-475c-ac68-bd0f2a9960ad'
|
||||||
object_type: 'network'
|
object_type: 'network'
|
||||||
target_project_id: 'a12f9ce1de0645e0a0b01c2e679f69ec'
|
|
||||||
project_id: '84b8774d595b41e89f3dfaa1fd76932d'
|
project_id: '84b8774d595b41e89f3dfaa1fd76932d'
|
||||||
|
target_project_id: 'a12f9ce1de0645e0a0b01c2e679f69ec'
|
||||||
|
|
||||||
# Update network RBAC policy
|
|
||||||
- name: Update an existing network RBAC policy
|
|
||||||
neutron_rbac_policy:
|
|
||||||
policy_id: 'f625242a-6a73-47ac-8d1f-91440b2c617f'
|
|
||||||
target_project_id: '163c89e065a94e069064e551e15daf0e'
|
|
||||||
|
|
||||||
# Delete an existing RBAC policy
|
|
||||||
- name: Delete RBAC policy
|
- name: Delete RBAC policy
|
||||||
openstack.cloud.openstack.neutron_rbac_policy:
|
openstack.cloud.openstack.neutron_rbac_policy:
|
||||||
policy_id: 'f625242a-6a73-47ac-8d1f-91440b2c617f'
|
id: 'f625242a-6a73-47ac-8d1f-91440b2c617f'
|
||||||
state: absent
|
state: absent
|
||||||
'''
|
'''
|
||||||
|
|
||||||
RETURN = r'''
|
RETURN = r'''
|
||||||
policy:
|
rbac_policy:
|
||||||
description:
|
description: A dictionary describing the RBAC policy.
|
||||||
- A hash representing the policy
|
|
||||||
type: complex
|
|
||||||
returned: always
|
returned: always
|
||||||
|
type: dict
|
||||||
contains:
|
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:
|
action:
|
||||||
description:
|
description:
|
||||||
- The access model specified by the RBAC rules
|
- The access model specified by the RBAC rules
|
||||||
@ -128,180 +113,182 @@ policy:
|
|||||||
- The name of the RBAC rule; usually null
|
- The name of the RBAC rule; usually null
|
||||||
type: str
|
type: str
|
||||||
sample: null
|
sample: null
|
||||||
location:
|
object_id:
|
||||||
description:
|
description:
|
||||||
- A dictionary of the project details to which access is granted
|
- 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"
|
||||||
|
policy:
|
||||||
|
description: Same as C(rbac_policy), kept for backward compatibility.
|
||||||
|
returned: always
|
||||||
type: dict
|
type: dict
|
||||||
sample: >-
|
|
||||||
{
|
|
||||||
"cloud": "devstack",
|
|
||||||
"region_name": "",
|
|
||||||
"zone": null,
|
|
||||||
"project": {
|
|
||||||
"id": "84b8774d595b41e89f3dfaa1fd76932c",
|
|
||||||
"name": null,
|
|
||||||
"domain_id": null,
|
|
||||||
"domain_name": null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||||
|
|
||||||
|
|
||||||
class NeutronRbacPolicy(OpenStackModule):
|
class NeutronRBACPolicy(OpenStackModule):
|
||||||
argument_spec = dict(
|
argument_spec = dict(
|
||||||
policy_id=dict(),
|
action=dict(choices=['access_as_external', 'access_as_shared']),
|
||||||
object_id=dict(), # ID of the object that this RBAC policy affects.
|
id=dict(aliases=['policy_id']),
|
||||||
object_type=dict(choices=['security_group', 'qos_policy', 'network']), # Type of the object that this RBAC policy affects.
|
object_id=dict(),
|
||||||
target_project_id=dict(), # The ID of the project this RBAC will be enforced.
|
object_type=dict(choices=['security_group', 'qos_policy', 'network']),
|
||||||
project_id=dict(), # The owner project ID.
|
project_id=dict(),
|
||||||
action=dict(choices=['access_as_external', 'access_as_shared']), # Action for the RBAC policy.
|
state=dict(default='present', choices=['absent', 'present']),
|
||||||
state=dict(default='present', choices=['absent', 'present'])
|
target_project_id=dict(),
|
||||||
)
|
)
|
||||||
|
|
||||||
module_kwargs = dict(
|
module_kwargs = dict(
|
||||||
|
required_if=[
|
||||||
|
('state', 'present', ('target_project_id',)),
|
||||||
|
('state', 'absent', ('id',)),
|
||||||
|
],
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _delete_rbac_policy(self, policy):
|
|
||||||
"""
|
|
||||||
Delete an existing RBAC policy
|
|
||||||
returns: the "Changed" state
|
|
||||||
"""
|
|
||||||
|
|
||||||
if policy is None:
|
|
||||||
self.fail_json(msg='Must specify policy_id for delete')
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.conn.network.delete_rbac_policy(policy.id)
|
|
||||||
except self.sdk.exceptions.OpenStackCloudException as ex:
|
|
||||||
self.fail_json(msg='Failed to delete RBAC policy: {0}'.format(str(ex)))
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def _create_rbac_policy(self):
|
|
||||||
"""
|
|
||||||
Creates a new RBAC policy
|
|
||||||
returns: the "Changed" state of the RBAC policy
|
|
||||||
"""
|
|
||||||
|
|
||||||
object_id = self.params.get('object_id')
|
|
||||||
object_type = self.params.get('object_type')
|
|
||||||
target_project_id = self.params.get('target_project_id')
|
|
||||||
project_id = self.params.get('project_id')
|
|
||||||
action = self.params.get('action')
|
|
||||||
|
|
||||||
attributes = {
|
|
||||||
'object_id': object_id,
|
|
||||||
'object_type': object_type,
|
|
||||||
'target_project_id': target_project_id,
|
|
||||||
'project_id': project_id,
|
|
||||||
'action': action
|
|
||||||
}
|
|
||||||
|
|
||||||
if not all(attributes.values()):
|
|
||||||
self.fail_json(msg='Missing one or more required parameter for creating a RBAC policy')
|
|
||||||
|
|
||||||
try:
|
|
||||||
search_attributes = dict(attributes)
|
|
||||||
del search_attributes['object_id']
|
|
||||||
del search_attributes['target_project_id']
|
|
||||||
policies = self.conn.network.rbac_policies(**search_attributes)
|
|
||||||
for p in policies:
|
|
||||||
if p.object_id == object_id and p.target_project_id == target_project_id:
|
|
||||||
return (False, p)
|
|
||||||
|
|
||||||
# if no matching policy exists, attempt to create one
|
|
||||||
policy = self.conn.network.create_rbac_policy(**attributes)
|
|
||||||
except self.sdk.exceptions.OpenStackCloudException as ex:
|
|
||||||
self.fail_json(msg='Failed to create RBAC policy: {0}'.format(str(ex)))
|
|
||||||
|
|
||||||
return (True, policy)
|
|
||||||
|
|
||||||
def _update_rbac_policy(self, policy):
|
|
||||||
"""
|
|
||||||
Updates an existing RBAC policy
|
|
||||||
returns: the "Changed" state of the RBAC policy
|
|
||||||
"""
|
|
||||||
|
|
||||||
object_id = self.params.get('object_id')
|
|
||||||
object_type = self.params.get('object_type')
|
|
||||||
target_project_id = self.params.get('target_project_id')
|
|
||||||
project_id = self.params.get('project_id')
|
|
||||||
action = self.params.get('action')
|
|
||||||
|
|
||||||
allowed_attributes = {
|
|
||||||
'rbac_policy': policy.id,
|
|
||||||
'target_project_id': target_project_id
|
|
||||||
}
|
|
||||||
|
|
||||||
disallowed_attributes = {
|
|
||||||
'object_id': object_id,
|
|
||||||
'object_type': object_type,
|
|
||||||
'project_id': project_id,
|
|
||||||
'action': action
|
|
||||||
}
|
|
||||||
|
|
||||||
if not all(allowed_attributes.values()):
|
|
||||||
self.fail_json(msg='Missing one or more required parameter for updating a RBAC policy')
|
|
||||||
|
|
||||||
if any(disallowed_attributes.values()):
|
|
||||||
self.fail_json(msg='Cannot change disallowed parameters while updating a RBAC policy: ["object_id", "object_type", "project_id", "action"]')
|
|
||||||
|
|
||||||
try:
|
|
||||||
policy = self.conn.network.update_rbac_policy(**allowed_attributes)
|
|
||||||
except self.sdk.exceptions.OpenStackCloudException as ex:
|
|
||||||
self.fail_json(msg='Failed to update the RBAC policy: {0}'.format(str(ex)))
|
|
||||||
|
|
||||||
return (True, policy)
|
|
||||||
|
|
||||||
def _policy_state_change(self, policy):
|
|
||||||
state = self.params['state']
|
|
||||||
if state == 'present':
|
|
||||||
if not policy:
|
|
||||||
return True
|
|
||||||
if state == 'absent' and policy:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
policy_id = self.params.get('policy_id')
|
state = self.params['state']
|
||||||
state = self.params.get('state')
|
|
||||||
|
|
||||||
if policy_id is not None:
|
policy = self._find()
|
||||||
try:
|
|
||||||
policy = self.conn.network.get_rbac_policy(policy_id)
|
|
||||||
except self.sdk.exceptions.ResourceNotFound:
|
|
||||||
policy = None
|
|
||||||
except self.sdk.exceptions.OpenStackCloudException as ex:
|
|
||||||
self.fail_json(msg='Failed to get RBAC policy: {0}'.format(str(ex)))
|
|
||||||
else:
|
|
||||||
policy = None
|
|
||||||
|
|
||||||
if self.ansible.check_mode:
|
if self.ansible.check_mode:
|
||||||
self.exit_json(changed=self._policy_state_change(policy), policy=policy)
|
self.exit_json(changed=self._will_change(state, policy))
|
||||||
|
|
||||||
if state == 'absent':
|
if state == 'present' and not policy:
|
||||||
if policy is None and policy_id:
|
# Create policy
|
||||||
|
policy = self._create()
|
||||||
|
self.exit_json(changed=True,
|
||||||
|
rbac_policy=policy.to_dict(computed=False),
|
||||||
|
policy=policy.to_dict(computed=False))
|
||||||
|
|
||||||
|
elif state == 'present' and policy:
|
||||||
|
# Update policy
|
||||||
|
update = self._build_update(policy)
|
||||||
|
if update:
|
||||||
|
policy = self._update(policy, update)
|
||||||
|
|
||||||
|
self.exit_json(changed=bool(update),
|
||||||
|
rbac_policy=policy.to_dict(computed=False),
|
||||||
|
policy=policy.to_dict(computed=False))
|
||||||
|
|
||||||
|
elif state == 'absent' and policy:
|
||||||
|
# Delete policy
|
||||||
|
self._delete(policy)
|
||||||
|
self.exit_json(changed=True)
|
||||||
|
|
||||||
|
elif state == 'absent' and not policy:
|
||||||
|
# Do nothing
|
||||||
self.exit_json(changed=False)
|
self.exit_json(changed=False)
|
||||||
if policy_id is None:
|
|
||||||
self.fail_json(msg='Must specify policy_id when state is absent')
|
|
||||||
if policy is not None:
|
|
||||||
changed = self._delete_rbac_policy(policy)
|
|
||||||
self.exit_json(changed=changed)
|
|
||||||
# state == 'present'
|
|
||||||
else:
|
|
||||||
if policy is None:
|
|
||||||
(changed, new_policy) = self._create_rbac_policy()
|
|
||||||
else:
|
|
||||||
(changed, new_policy) = self._update_rbac_policy(policy)
|
|
||||||
|
|
||||||
self.exit_json(changed=changed, policy=new_policy)
|
def _build_update(self, policy):
|
||||||
|
update = {}
|
||||||
|
|
||||||
|
non_updateable_keys = [k for k in ['object_id', 'object_type',
|
||||||
|
'project_id', 'action']
|
||||||
|
if self.params[k] is not None
|
||||||
|
and self.params[k] != policy[k]]
|
||||||
|
|
||||||
|
if non_updateable_keys:
|
||||||
|
self.fail_json(msg='Cannot update parameters {0}'
|
||||||
|
.format(non_updateable_keys))
|
||||||
|
|
||||||
|
attributes = dict((k, self.params[k])
|
||||||
|
for k in ['target_project_id']
|
||||||
|
if self.params[k] is not None
|
||||||
|
and self.params[k] != policy[k])
|
||||||
|
|
||||||
|
if attributes:
|
||||||
|
update['attributes'] = attributes
|
||||||
|
|
||||||
|
return update
|
||||||
|
|
||||||
|
def _create(self):
|
||||||
|
kwargs = dict((k, self.params[k])
|
||||||
|
for k in ['object_id', 'object_type',
|
||||||
|
'target_project_id', 'project_id',
|
||||||
|
'action']
|
||||||
|
if self.params[k] is not None)
|
||||||
|
|
||||||
|
return self.conn.network.create_rbac_policy(**kwargs)
|
||||||
|
|
||||||
|
def _delete(self, policy):
|
||||||
|
self.conn.network.delete_rbac_policy(policy.id)
|
||||||
|
|
||||||
|
def _find(self):
|
||||||
|
id = self.params['id']
|
||||||
|
|
||||||
|
if id is not None:
|
||||||
|
return self.conn.network.find_rbac_policy(id)
|
||||||
|
|
||||||
|
matches = self._find_matches()
|
||||||
|
if len(matches) > 1:
|
||||||
|
self.fail_json(msg='Found more a single matching RBAC policy'
|
||||||
|
' which match the given parameters.')
|
||||||
|
elif len(matches) == 1:
|
||||||
|
return matches[0]
|
||||||
|
else: # len(matches) == 0
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _find_matches(self):
|
||||||
|
missing_keys = [k for k in ['action', 'object_id', 'object_type',
|
||||||
|
'project_id', 'target_project_id']
|
||||||
|
if self.params[k] is None]
|
||||||
|
if missing_keys:
|
||||||
|
self.fail_json(msg='Missing parameter(s) for finding'
|
||||||
|
' a matching RBAC policy: {0}'
|
||||||
|
.format(', '.join(missing_keys)))
|
||||||
|
|
||||||
|
kwargs = dict((k, self.params[k])
|
||||||
|
for k in ['action', 'object_type', 'project_id'])
|
||||||
|
|
||||||
|
policies = self.conn.network.rbac_policies(**kwargs)
|
||||||
|
|
||||||
|
return [p for p in policies
|
||||||
|
if any(p[k] == self.params[k]
|
||||||
|
for k in ['object_id', 'target_project_id'])]
|
||||||
|
|
||||||
|
def _update(self, policy, update):
|
||||||
|
attributes = update.get('attributes')
|
||||||
|
if attributes:
|
||||||
|
policy = self.conn.network.update_rbac_policy(policy.id,
|
||||||
|
**attributes)
|
||||||
|
|
||||||
|
return policy
|
||||||
|
|
||||||
|
def _will_change(self, state, policy):
|
||||||
|
if state == 'present' and not policy:
|
||||||
|
return True
|
||||||
|
elif state == 'present' and policy:
|
||||||
|
return bool(self._build_update(policy))
|
||||||
|
elif state == 'absent' and policy:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
# state == 'absent' and not policy:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
module = NeutronRbacPolicy()
|
module = NeutronRBACPolicy()
|
||||||
module()
|
module()
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user