Firewalld: Add functionality to set forwarding
SUMMARY
Adds firewalld functionality to do the equivalent of firewall-cmd --add-forwarding --zone={zone}.
Functionality is exactly analogous to the firewall-cmd --add-masquerade --zone={zone} already present.
Fixes#529
ISSUE TYPE
Feature Pull Request
COMPONENT NAME
firewalld
ADDITIONAL INFORMATION
Usage:
- ansible.posix.firewalld:
forward: true
state: enabled
permanent: true
zone: internal
Reviewed-by: Abhijeet Kasurde
Reviewed-by: Hideki Saito <saito@fgrep.org>
Sometimes it's necessary to configure SELinux before it's enabled on the
system. There's `ignore_selinux_state` which should allow it. Before
this change `seboolean` module failed on SELinux disabled system even
with `ignore_selinux_state: true` and SELinux policy installed while
`semanage boolean` worked as expected:
$ ansible -i 192.168.121.153, -m seboolean -a "name=ssh_sysadm_login state=on ignore_selinux_state=true" all
192.168.121.153 | FAILED! => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"msg": "Failed to get list of boolean names"
}
$ ssh root@192.168.121.153 semanage boolean -l | grep ssh_sysadm_login
ssh_sysadm_login (off , off) Allow ssh to sysadm login
It's caused by `selinux.security_get_boolean_names()` and
`selinux.security_get_boolean_active(name)` which required SELinux
enabled system.
This change adds a fallback to semanage API which works in SELinux
disabled system when SELinux targeted policy is installed:
ANSIBLE_LIBRARY=plugins/modules ansible -i 192.168.121.153, -m seboolean -a "name=ssh_sysadm_login state=on persistent=true ignore_selinux_state=true" all
192.168.121.153 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"name": "ssh_sysadm_login",
"persistent": true,
"state": true
}
$ ssh root@192.168.121.153 semanage boolean -l | grep ssh_sysadm_login
ssh_sysadm_login (on , on) Allow ssh to sysadm login
Note that without `persistent=true` this module is effectively NO-OP now.
Signed-off-by: Petr Lautrbach <lautrbach@redhat.com>
the CI failures are unrelated and shouldn't even be showing up ... I'm going to sort that out separately but that doesn't need to prevent this merge, all relevant CI tests passed
firewalld: make offline do something
SUMMARY
ansible.posix.firewalld has an offline flag, but it currently does not do anything. What most people expect it to do is allow the task to proceed even when firewalld is offline, so it makes the most sense for it to override the immediate flag and prevent the module from throwing an error in that case.
Fixes#81.
ISSUE TYPE
Feature Pull Request
COMPONENT NAME
firewalld
ADDITIONAL INFORMATION
Reviewed-by: Adam Miller <admiller@redhat.com>
The seboolean, selinux, firewalld, and firewalld_info modules depend on
system bindings that are only available for the default system python
interpreter. ansible-core is not packaged for the default system python
interpreter on RHEL 8 and 9. When automatic interpreter discovery does
not occur (e.g. when using implicit localhost [1]), ansible-core will
not use the system interpreter to run ansible modules and the
aforementioned modules will not work even if the bindings are installed.
The RHEL ansible-core maintainers as well as the EPEL ansible and
ansible-collection-* package maintainers (inc. me) have gotten multiple
bug reports about this. We have been telling people to fix their setup
to use the correct Python interpreter. Fortunately, ansible-core 2.11
and above have a module utility that'll respawn modules to use the
correct system interpreter.
[1] https://docs.ansible.com/ansible/latest/inventory/implicit_localhost.html
json[l] callback: add parameter to set JSON prettyprint indent level
SUMMARY
Add ANSIBLE_JSON_INDENT parameter to both the json and jsonl callback plugins. The default values are different between the two modules to maintain their existing behavior:
json: indent==4, causing a prettyprint output
jsonl: indent==0, causing a 1-line output
ISSUE TYPE
Feature Pull Request
COMPONENT NAME
ansible.posix.json
ansible.posix.jsonl
ADDITIONAL INFORMATION
One specific use-case that is enabled by this feature: if a user chooses to use the jsonl plugin so that they still get output at the end of each task (vs. only at the end of the play), they may also want human-readable output so that they can monitor the status of their play. For example, setting the jsonl indent level to 4 gives a) output at the end of each task, and b) making that output be both machine readable and human readable.
Using this trivial playbook shows the change:
- hosts: localhost
gather_facts: false
tasks:
- name: hello, world
debug:
msg: hello, world
When using the jsonl callback, here's what one JSON emit looks like before the change:
{"_event":"v2_playbook_on_play_start","_timestamp":"2023-04-08T12:11:48.001806Z","play":{"duration":{"start":"2023-04-08T12:11:48.001383Z"},"id":"acde4800-1122-f32c-94c3-000000000001","name":"localhost"},"tasks":[]}
After the change, setting ANSIBLE_JSON_INDENT to 4, the same output looks like this:
{
"_event":"v2_playbook_on_play_start",
"_timestamp":"2023-04-08T12:12:47.787516Z",
"play":{
"duration":{
"start":"2023-04-08T12:12:47.787164Z"
},
"id":"acde4800-1122-2946-e3e4-000000000001",
"name":"localhost"
},
"tasks":[]
}
Both outputs are suitable for automated processes to parse the machine readable output. The second output has the benefit of being human readable.
Reviewed-by: Adam Miller <admiller@redhat.com>
Reviewed-by: Jeff Squyres
Add ANSIBLE_JSON_INDENT parameter to both the json and jsonl callback
plugins. The default values are different between the two modules to
maintain their existing behavior:
* json: indent==4, causing a prettyprint output
* jsonl: indent==0, causing a 1-line output
One specific use-case that is enabled by this feature: if a user
chooses to use the jsonl plugin so that they still get output at the
end of each task (vs. only at the end of the play), they may also want
human-readable output so that they can monitor the status of their
play. For example, setting the jsonl indent level to 4 gives a)
output at the end of each task, and b) making that output be both
machine readable and human readable.
Signed-off-by: Jeff Squyres <jsquyres@cisco.com>
json[l] callback: add play/task path info
Add the play and task path info (i.e., filename and line number) to the JSON that is emitted from the json and jsonl callback plugins, allowing more accurate post-mortem analysis.
SUMMARY
Add the play and task path info (i.e., filename and line number) to the JSON that is emitted from the json and jsonl callback plugins, allowing more accurate post-mortem analysis.
ISSUE TYPE
Feature Pull Request
COMPONENT NAME
ansible.posix.json
ansible.posix.jsonl
ADDITIONAL INFORMATION
By also including the file/line number in the JSON data emitted, post-mortem analysis can unambiguously tie play/task log data to the specific play / task that generated it. Without this information, it could be difficult for automated processes to precisely map log output back to the task that generated it (especially with playbooks that either do not name tasks, or do not name tasks uniquely).
Using this trivial playbook shows the change:
- hosts: localhost
gather_facts: false
tasks:
- name: hello, world
debug:
msg: hello, world
When using the json callback, here's what it looks like before the change (for brevity, just the plays section of the output):
{
"play": {
"duration": {
"end": "2023-04-08T11:35:39.694000Z",
"start": "2023-04-08T11:35:39.657056Z"
},
"id": "acde4800-1122-6387-7abd-000000000001",
"name": "localhost",
},
"tasks": [
{
"hosts": {
"localhost": {
"_ansible_no_log": null,
"_ansible_verbose_always": true,
"action": "debug",
"changed": false,
"msg": "hello, world"
}
},
"task": {
"duration": {
"end": "2023-04-08T11:35:39.694000Z",
"start": "2023-04-08T11:35:39.672132Z"
},
"id": "acde4800-1122-6387-7abd-000000000003",
"name": "hello, world",
}
}
]
}
After the change, there is a new path key/value in both the play and the task:
{
"play": {
"duration": {
"end": "2023-04-08T11:35:39.694000Z",
"start": "2023-04-08T11:35:39.657056Z"
},
"id": "acde4800-1122-6387-7abd-000000000001",
"name": "localhost",
"path": "/tmp/plays/hello.yaml:1"
},
"tasks": [
{
"hosts": {
"localhost": {
"_ansible_no_log": null,
"_ansible_verbose_always": true,
"action": "debug",
"changed": false,
"msg": "hello, world"
}
},
"task": {
"duration": {
"end": "2023-04-08T11:35:39.694000Z",
"start": "2023-04-08T11:35:39.672132Z"
},
"id": "acde4800-1122-6387-7abd-000000000003",
"name": "hello, world",
"path": "/tmp/plays/hello.yaml:4"
}
}
]
}
The effect is the same in the jsonl plugin, but the output is squashed into a single line.
Reviewed-by: Adam Miller <admiller@redhat.com>
docs: fix profile_tasks callback documentation
SUMMARY
This fixes the markup.
Fixes: #412
ISSUE TYPE
Docs Pull Request
COMPONENT NAME
profile_tasks
ADDITIONAL INFORMATION
None.
Reviewed-by: Hideki Saito <saito@fgrep.org>
Reviewed-by: Adam Miller <admiller@redhat.com>
Fix adding interface to zone when firewalld is offline
SUMMARY
Fixes issue #357
The existing implementation had several issues which have been resolved by this PR:
incorrectly assumed some zone always exists that contains the interface
incorrectly included the logic to add the interface to the target zone inside of the condition checking if the interface is already assigned to a different zone (and needs to be removed)
passed an invalid argument to the constructor for FirewallClientZoneSettings
ISSUE TYPE
Bugfix Pull Request
COMPONENT NAME
ansible.posix.firewalld
ADDITIONAL INFORMATION
- name: Add lo interface to trusted zone
ansible.posix.firewalld:
interface: lo
zone: trusted
permanent: Yes
state: enabled
Before
TASK [firewalld : Add lo interface to trusted zone] ****************************
task path: /root/ansible_collections/ansible/posix/tests/output/.tmp/integration/firewalld-gpgqwc7n-ÅÑŚÌβŁÈ/tests/integration/targets/firewalld/tasks/interface_test_cases.yml:7
Using module file /root/ansible_collections/ansible/posix/plugins/modules/firewalld.py
Pipelining is enabled.
<testhost> ESTABLISH LOCAL CONNECTION FOR USER: root
<testhost> EXEC /bin/sh -c '/usr/bin/python3.10 && sleep 0'
The full traceback is:
File "/tmp/ansible_ansible.posix.firewalld_payload_2vetziz9/ansible_ansible.posix.firewalld_payload.zip/ansible_collections/ansible/posix/plugins/module_utils/firewalld.py", line 112, in action_handler
return action_func(*action_func_args)
File "/tmp/ansible_ansible.posix.firewalld_payload_2vetziz9/ansible_ansible.posix.firewalld_payload.zip/ansible_collections/ansible/posix/plugins/modules/firewalld.py", line 481, in set_enabled_permanent
fatal: [testhost]: FAILED! => {
"changed": false,
"invocation": {
"module_args": {
"icmp_block": null,
"icmp_block_inversion": null,
"immediate": false,
"interface": "lo",
"masquerade": null,
"offline": null,
"permanent": true,
"port": null,
"port_forward": null,
"rich_rule": null,
"service": null,
"source": null,
"state": "enabled",
"target": null,
"timeout": 0,
"zone": "trusted"
}
},
"msg": "ERROR: Exception caught: list index out of range Permanent operation"
}
After
TASK [firewalld : Add lo interface to trusted zone] ****************************
task path: /root/ansible_collections/ansible/posix/tests/output/.tmp/integration/firewalld-tr92i6e1-ÅÑŚÌβŁÈ/tests/integration/targets/firewalld/tasks/interface_test_cases.yml:7
Using module file /root/ansible_collections/ansible/posix/plugins/modules/firewalld.py
Pipelining is enabled.
<testhost> ESTABLISH LOCAL CONNECTION FOR USER: root
<testhost> EXEC /bin/sh -c '/usr/bin/python3.10 && sleep 0'
changed: [testhost] => {
"changed": true,
"invocation": {
"module_args": {
"icmp_block": null,
"icmp_block_inversion": null,
"immediate": false,
"interface": "lo",
"masquerade": null,
"offline": null,
"permanent": true,
"port": null,
"port_forward": null,
"rich_rule": null,
"service": null,
"source": null,
"state": "enabled",
"target": null,
"timeout": 0,
"zone": "trusted"
}
},
"msg": "Permanent operation, Changed lo to zone trusted, (offline operation: only on-disk configs were altered)"
}
Reviewed-by: Adam Miller <admiller@redhat.com>
Add the play and task path info (i.e., filename and line number) to
the JSON that is emitted from the json and jsonl callback plugins,
allowing more accurate post-mortem analysis.
Signed-off-by: Jeff Squyres <jsquyres@cisco.com>
firewalld_info: fixed typo in default_zone and improved examples
SUMMARY
There was a typo in the docs of firewalld_info. Furthermore I slightly improved the examples by showcasing how to use the data gathered by this module.
ISSUE TYPE
Docs Pull Request
COMPONENT NAME
firewalld_info
ADDITIONAL INFORMATION
I'm not sure whether I should also update the file docs/ansible.posix.firewalld_info_module.rst but I suspect it will be generated automatically?
Reviewed-by: Hideki Saito <saito@fgrep.org>
The rhel_facts module must use keyword arguments. The current
code gives this error:
```
Traceback (most recent call last):
...
File "/tmp/ansible_ansible.posix.rhel_facts_payload_y10oy_4m/.../rhel_facts.py", line 72, in main
TypeError: exit_json() takes 1 positional argument but 2 were given
```
The fix is to use all keyword arguments like other facts plugins.
firewalld: Add support for protocol parameter
SUMMARY
Fixes#416 - This PR implements the --add-protocol/--remove-protocol parameters for firewalld.
I have just copied and rewritten the code from service parameter. Please look carefully :)
ISSUE TYPE
Feature Pull Request
COMPONENT NAME
firewalld
ADDITIONAL INFORMATION
- name: Allow OSPF traffic
ansible.posix.firewalld:
protocol: ospf
zone: work
state: enabled
permanent: true
Reviewed-by: Hideki Saito <saito@fgrep.org>
Updat ZoneTransaction to support operations when firewalld is offline
SUMMARY
Fixes#398 by checking the flag self.fw_offline and calling the offline specific APIs when the flag is true.
ISSUE TYPE
Bugfix Pull Request
COMPONENT NAME
ansible.posix.firewalld
ADDITIONAL INFORMATION
When attempting to add or remove zones, the ansible.posix.firewalld module would always call APIs as if it was online.
Specifically, the ZoneTransaction class assumed that self.fw was a FirewallClient, but when the daemon is offline, it is instead either a Firewall or Firewall_test based on the version of firewalld installed.
See #398 for additional background.
Sample task
- name: 'Zone example - Create new zone'
ansible.posix.firewalld:
zone: "example"
state: "present"
permanent: Yes
Before
The full traceback is:
File "/tmp/ansible_ansible.posix.firewalld_payload_04lptorx/ansible_ansible.posix.firewalld_payload.zip/ansible_collections/ansible/posix/plugins/module_utils/firewalld.py", line 111, in action_handler
return action_func(*action_func_args)
File "/tmp/ansible_ansible.posix.firewalld_payload_04lptorx/ansible_ansible.posix.firewalld_payload.zip/ansible_collections/ansible/posix/plugins/modules/firewalld.py", line 678, in get_enabled_permanent
fatal: [boot]: FAILED! => {
"changed": false,
"invocation": {
"module_args": {
"icmp_block": null,
"icmp_block_inversion": null,
"immediate": false,
"interface": null,
"masquerade": null,
"offline": null,
"permanent": true,
"port": null,
"port_forward": null,
"rich_rule": null,
"service": null,
"source": null,
"state": "present",
"target": null,
"timeout": 0,
"zone": "example"
}
},
"msg": "ERROR: Exception caught: 'FirewallConfig' object is not callable"
}
After
changed: [boot] => {
"changed": true,
"invocation": {
"module_args": {
"icmp_block": null,
"icmp_block_inversion": null,
"immediate": false,
"interface": null,
"masquerade": null,
"offline": null,
"permanent": true,
"port": null,
"port_forward": null,
"rich_rule": null,
"service": null,
"source": null,
"state": "present",
"target": null,
"timeout": 0,
"zone": "example"
}
},
"msg": "Permanent operation, Added zone example, Changed zone example to present, (offline operation: only on-disk configs were altered)"
Reviewed-by: Gonéri Le Bouder <goneri@lebouder.net>
Fix boolean values in docs
SUMMARY
Fixes#397
ISSUE TYPE
Docs Pull Request
COMPONENT NAME
Docs of several modules
ADDITIONAL INFORMATION
Notes about testing. I'm not sure how to test collections properly. I have ran ansible-test sanity --python 3.10 and ansible-test units --python 3.10 in venv with ansible-core 2.14 (with 0 return code in both cases). To run units test successfully I had to install pytest-forked pip package in addition to this one pytest-xdist from test-requirements.txt.
Note about issue #397. I haven't changed yes here because in this case it is value from /etc/vfstab. Also I've changed yes for parameters masquerade and icmp_block_inversion because they both are converted to bool by boolean function and will be changed to boolean in a future release (1, 2), for required too.
Reviewed-by: Felix Fontein <felix@fontein.de>
Reviewed-by: Hideki Saito <saito@fgrep.org>
ansible.posix.mount: add absent_from_fstab option
SUMMARY
Add absent_from_fstab option to remove the entry from fstab, but not unmount or delete the folder. Ideally this would have been the behavior of absent (as to mirror the behavior of present), but for backward compatibility I added a new verbose state
ISSUE TYPE
Feature Pull Request
COMPONENT NAME
mount
ADDITIONAL INFORMATION
Sometimes you may not want to delete the mountpoint (e.g. if it is not currently mounted and data is in the directory, the current behavior will simply error).
Reviewed-by: Amin Vakil <None>
Reviewed-by: None <None>
Fixes#390. Hosts involved must have same password
SUMMARY
Fixes#390
The change takes the password from destination hostvars ansible_ssh_pass or ansible_password when dest is remote.
In other case, previous behavior is maintained and password is taken form task vars ansible_ssh_pass or ansible_password.
Also, both user and password are templated to allow jinja expressions in them.
ISSUE TYPE
Bugfix Pull Request
COMPONENT NAME
ansible.posix.synchronize
ADDITIONAL INFORMATION
n/a
Reviewed-by: Adam Miller <admiller@redhat.com>