From c1573ffdbb1fb8a7183971fb5af5fd7a7ba4b1a7 Mon Sep 17 00:00:00 2001 From: Petr Lautrbach Date: Tue, 30 Aug 2022 13:32:07 +0200 Subject: [PATCH] seport: add `local` argument Using `local: true` users can enforce to work only with local policy modifications. i.e. # Without `local`, no new modification is added when port already exists $ sudo ansible -m seport -a 'ports=22 state=present setype=ssh_port_t proto=tcp' localhost localhost | SUCCESS => { "changed": false, "ports": [ "22" ], "proto": "tcp", "setype": "ssh_port_t", "state": "present" } $ sudo semanage port -l -C # With `local`, a port is always added/changed in local modification list $ sudo ansible -m seport -a 'ports=22 state=present setype=ssh_port_t proto=tcp local=true' localhost localhost | CHANGED => { "changed": true, "ports": [ "22" ], "proto": "tcp", "setype": "ssh_port_t", "state": "present" } $ sudo semanage port -l -C SELinux Port Type Proto Port Number ssh_port_t tcp 22 # With `local`, seport removes the port only from local modifications $ sudo ansible -m seport -a 'ports=22 state=absent setype=ssh_port_t proto=tcp local=true' localhost localhost | CHANGED => { "changed": true, "ports": [ "22" ], "proto": "tcp", "setype": "ssh_port_t", "state": "absent" } $ sudo semanage port -l -C # Even though the port is still defined in system policy, the module # result is success as there's no port local modification $ sudo ansible -m seport -a 'ports=22 state=absent setype=ssh_port_t proto=tcp local=true' localhost localhost | SUCCESS => { "changed": false, "ports": [ "22" ], "proto": "tcp", "setype": "ssh_port_t", "state": "absent" } # But it fails without `local` as it tries to remove port defined in # system policy $ sudo ansible -m seport -a 'ports=22 state=absent setype=ssh_port_t proto=tcp' localhost An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ValueError: Port tcp/22 is defined in policy, cannot be deleted localhost | FAILED! => { "changed": false, "msg": "ValueError: Port tcp/22 is defined in policy, cannot be deleted\n" } Signed-off-by: Petr Lautrbach --- plugins/modules/system/seport.py | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/plugins/modules/system/seport.py b/plugins/modules/system/seport.py index 65cf09e22d1..d5a32e5aba7 100644 --- a/plugins/modules/system/seport.py +++ b/plugins/modules/system/seport.py @@ -49,6 +49,11 @@ - Run independent of selinux runtime state type: bool default: false + local: + description: + - Work with local modifications only. + type: bool + default: false notes: - The changes are persistent across reboots. - Not tested on any debian based system. @@ -89,6 +94,14 @@ proto: tcp setype: memcache_port_t state: present + +- name: Remove tcp port 22 local modification if exists + local_seport: + ports: 22 + protocol: tcp + setype: http_port_t + state: absent + local: yes ''' import traceback @@ -117,7 +130,7 @@ def get_runtime_status(ignore_selinux_state=False): return ignore_selinux_state or selinux.is_selinux_enabled() -def semanage_port_get_ports(seport, setype, proto): +def semanage_port_get_ports(seport, setype, proto, local): """ Get the list of ports that have the specified type definition. :param community.general.seport: Instance of seobject.portRecords @@ -131,7 +144,7 @@ def semanage_port_get_ports(seport, setype, proto): :rtype: list :return: List of ports that have the specified SELinux type. """ - records = seport.get_all_by_type() + records = seport.get_all_by_type(locallist=local) if (setype, proto) in records: return records[(setype, proto)] else: @@ -165,7 +178,7 @@ def semanage_port_get_type(seport, port, proto): return records.get(key) -def semanage_port_add(module, ports, proto, setype, do_reload, serange='s0', sestore=''): +def semanage_port_add(module, ports, proto, setype, do_reload, serange='s0', sestore='', local=False): """ Add SELinux port type definition to the policy. :type module: AnsibleModule @@ -196,7 +209,7 @@ def semanage_port_add(module, ports, proto, setype, do_reload, serange='s0', ses try: seport = seobject.portRecords(sestore) seport.set_reload(do_reload) - ports_by_type = semanage_port_get_ports(seport, setype, proto) + ports_by_type = semanage_port_get_ports(seport, setype, proto, local) for port in ports: if port in ports_by_type: continue @@ -216,7 +229,7 @@ def semanage_port_add(module, ports, proto, setype, do_reload, serange='s0', ses return change -def semanage_port_del(module, ports, proto, setype, do_reload, sestore=''): +def semanage_port_del(module, ports, proto, setype, do_reload, sestore='', local=False): """ Delete SELinux port type definition from the policy. :type module: AnsibleModule @@ -244,7 +257,7 @@ def semanage_port_del(module, ports, proto, setype, do_reload, sestore=''): try: seport = seobject.portRecords(sestore) seport.set_reload(do_reload) - ports_by_type = semanage_port_get_ports(seport, setype, proto) + ports_by_type = semanage_port_get_ports(seport, setype, proto, local) for port in ports: if port in ports_by_type: change = True @@ -266,6 +279,7 @@ def main(): setype=dict(type='str', required=True), state=dict(type='str', default='present', choices=['absent', 'present']), reload=dict(type='bool', default=True), + local=dict(type='bool', default=False) ), supports_check_mode=True, ) @@ -286,6 +300,7 @@ def main(): setype = module.params['setype'] state = module.params['state'] do_reload = module.params['reload'] + local = module.params['local'] result = { 'ports': ports, @@ -295,9 +310,9 @@ def main(): } if state == 'present': - result['changed'] = semanage_port_add(module, ports, proto, setype, do_reload) + result['changed'] = semanage_port_add(module, ports, proto, setype, do_reload, local=local) elif state == 'absent': - result['changed'] = semanage_port_del(module, ports, proto, setype, do_reload) + result['changed'] = semanage_port_del(module, ports, proto, setype, do_reload, local=local) else: module.fail_json(msg='Invalid value of argument "state": {0}'.format(state))