summaryrefslogtreecommitdiffstats
path: root/roles/os_firewall
diff options
context:
space:
mode:
authorScott Dodson <sdodson@redhat.com>2017-08-11 12:03:58 -0400
committerGitHub <noreply@github.com>2017-08-11 12:03:58 -0400
commit3409e6db205b6b24914e16c62972de50071f4051 (patch)
treedbfacaf9d6640241ee5dd7a2446d330a4e12283e /roles/os_firewall
parent57d7984bc7d7f64184c0defd3cc305cb3ef2708f (diff)
parent7d50ffe98dfa17e3fb72627699c794843ed5295d (diff)
downloadopenshift-3409e6db205b6b24914e16c62972de50071f4051.tar.gz
openshift-3409e6db205b6b24914e16c62972de50071f4051.tar.bz2
openshift-3409e6db205b6b24914e16c62972de50071f4051.tar.xz
openshift-3409e6db205b6b24914e16c62972de50071f4051.zip
Merge pull request #4797 from kwoodson/os_firewall_refactor
Refactor the firewall workflow.
Diffstat (limited to 'roles/os_firewall')
-rw-r--r--roles/os_firewall/README.md37
-rw-r--r--roles/os_firewall/defaults/main.yml2
-rwxr-xr-xroles/os_firewall/library/os_firewall_manage_iptables.py283
-rw-r--r--roles/os_firewall/tasks/firewall/firewalld.yml16
-rw-r--r--roles/os_firewall/tasks/firewall/iptables.yml16
5 files changed, 14 insertions, 340 deletions
diff --git a/roles/os_firewall/README.md b/roles/os_firewall/README.md
index e7ef544f4..be0b8291a 100644
--- a/roles/os_firewall/README.md
+++ b/roles/os_firewall/README.md
@@ -1,8 +1,8 @@
OS Firewall
===========
-OS Firewall manages firewalld and iptables firewall settings for a minimal use
-case (Adding/Removing rules based on protocol and port number).
+OS Firewall manages firewalld and iptables installation.
+case.
Note: firewalld is not supported on Atomic Host
https://bugzilla.redhat.com/show_bug.cgi?id=1403331
@@ -18,8 +18,6 @@ Role Variables
| Name | Default | |
|---------------------------|---------|----------------------------------------|
| os_firewall_use_firewalld | False | If false, use iptables |
-| os_firewall_allow | [] | List of service,port mappings to allow |
-| os_firewall_deny | [] | List of service, port mappings to deny |
Dependencies
------------
@@ -29,34 +27,27 @@ None.
Example Playbook
----------------
-Use iptables and open tcp ports 80 and 443:
+Use iptables:
```
---
- hosts: servers
- vars:
- os_firewall_use_firewalld: false
- os_firewall_allow:
- - service: httpd
- port: 80/tcp
- - service: https
- port: 443/tcp
- roles:
- - os_firewall
+ task:
+ - include_role:
+ name: os_firewall
+ vars:
+ os_firewall_use_firewalld: false
```
-Use firewalld and open tcp port 443 and close previously open tcp port 80:
+Use firewalld:
```
---
- hosts: servers
vars:
- os_firewall_allow:
- - service: https
- port: 443/tcp
- os_firewall_deny:
- - service: httpd
- port: 80/tcp
- roles:
- - os_firewall
+ tasks:
+ - include_role:
+ name: os_firewall
+ vars:
+ os_firewall_use_firewalld: true
```
License
diff --git a/roles/os_firewall/defaults/main.yml b/roles/os_firewall/defaults/main.yml
index 01859e5fc..f96a80f1c 100644
--- a/roles/os_firewall/defaults/main.yml
+++ b/roles/os_firewall/defaults/main.yml
@@ -3,5 +3,3 @@ os_firewall_enabled: True
# firewalld is not supported on Atomic Host
# https://bugzilla.redhat.com/show_bug.cgi?id=1403331
os_firewall_use_firewalld: "{{ False }}"
-os_firewall_allow: []
-os_firewall_deny: []
diff --git a/roles/os_firewall/library/os_firewall_manage_iptables.py b/roles/os_firewall/library/os_firewall_manage_iptables.py
deleted file mode 100755
index aeee3ede8..000000000
--- a/roles/os_firewall/library/os_firewall_manage_iptables.py
+++ /dev/null
@@ -1,283 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# pylint: disable=fixme, missing-docstring
-import subprocess
-
-DOCUMENTATION = '''
----
-module: os_firewall_manage_iptables
-short_description: This module manages iptables rules for a given chain
-author: Jason DeTiberus
-requirements: [ ]
-'''
-EXAMPLES = '''
-'''
-
-
-class IpTablesError(Exception):
- def __init__(self, msg, cmd, exit_code, output):
- super(IpTablesError, self).__init__(msg)
- self.msg = msg
- self.cmd = cmd
- self.exit_code = exit_code
- self.output = output
-
-
-class IpTablesAddRuleError(IpTablesError):
- pass
-
-
-class IpTablesRemoveRuleError(IpTablesError):
- def __init__(self, chain, msg, cmd, exit_code, output): # pylint: disable=too-many-arguments, line-too-long, redefined-outer-name
- super(IpTablesRemoveRuleError, self).__init__(msg, cmd, exit_code,
- output)
- self.chain = chain
-
-
-class IpTablesSaveError(IpTablesError):
- pass
-
-
-class IpTablesCreateChainError(IpTablesError):
- def __init__(self, chain, msg, cmd, exit_code, output): # pylint: disable=too-many-arguments, line-too-long, redefined-outer-name
- super(IpTablesCreateChainError, self).__init__(msg, cmd, exit_code,
- output)
- self.chain = chain
-
-
-class IpTablesCreateJumpRuleError(IpTablesError):
- def __init__(self, chain, msg, cmd, exit_code, output): # pylint: disable=too-many-arguments, line-too-long, redefined-outer-name
- super(IpTablesCreateJumpRuleError, self).__init__(msg, cmd, exit_code,
- output)
- self.chain = chain
-
-
-# TODO: implement rollbacks for any events that were successful and an
-# exception was thrown later. For example, when the chain is created
-# successfully, but the add/remove rule fails.
-class IpTablesManager(object): # pylint: disable=too-many-instance-attributes
- def __init__(self, module):
- self.module = module
- self.ip_version = module.params['ip_version']
- self.check_mode = module.check_mode
- self.chain = module.params['chain']
- self.create_jump_rule = module.params['create_jump_rule']
- self.jump_rule_chain = module.params['jump_rule_chain']
- self.cmd = self.gen_cmd()
- self.save_cmd = self.gen_save_cmd()
- self.output = []
- self.changed = False
-
- def save(self):
- try:
- self.output.append(subprocess.check_output(self.save_cmd, stderr=subprocess.STDOUT))
- except subprocess.CalledProcessError as ex:
- raise IpTablesSaveError(
- msg="Failed to save iptables rules",
- cmd=ex.cmd, exit_code=ex.returncode, output=ex.output)
-
- def verify_chain(self):
- if not self.chain_exists():
- self.create_chain()
- if self.create_jump_rule and not self.jump_rule_exists():
- self.create_jump()
-
- def add_rule(self, port, proto):
- rule = self.gen_rule(port, proto)
- if not self.rule_exists(rule):
- self.verify_chain()
-
- if self.check_mode:
- self.changed = True
- self.output.append("Create rule for %s %s" % (proto, port))
- else:
- cmd = self.cmd + ['-A'] + rule
- try:
- self.output.append(subprocess.check_output(cmd))
- self.changed = True
- self.save()
- except subprocess.CalledProcessError as ex:
- raise IpTablesCreateChainError(
- chain=self.chain,
- msg="Failed to create rule for "
- "%s %s" % (proto, port),
- cmd=ex.cmd, exit_code=ex.returncode,
- output=ex.output)
-
- def remove_rule(self, port, proto):
- rule = self.gen_rule(port, proto)
- if self.rule_exists(rule):
- if self.check_mode:
- self.changed = True
- self.output.append("Remove rule for %s %s" % (proto, port))
- else:
- cmd = self.cmd + ['-D'] + rule
- try:
- self.output.append(subprocess.check_output(cmd))
- self.changed = True
- self.save()
- except subprocess.CalledProcessError as ex:
- raise IpTablesRemoveRuleError(
- chain=self.chain,
- msg="Failed to remove rule for %s %s" % (proto, port),
- cmd=ex.cmd, exit_code=ex.returncode, output=ex.output)
-
- def rule_exists(self, rule):
- check_cmd = self.cmd + ['-C'] + rule
- return True if subprocess.call(check_cmd) == 0 else False
-
- @staticmethod
- def port_as_argument(port):
- if isinstance(port, int):
- return str(port)
- if isinstance(port, basestring): # noqa: F405
- return port.replace('-', ":")
- return port
-
- def gen_rule(self, port, proto):
- return [self.chain, '-p', proto, '-m', 'state', '--state', 'NEW',
- '-m', proto, '--dport', IpTablesManager.port_as_argument(port), '-j', 'ACCEPT']
-
- def create_jump(self):
- if self.check_mode:
- self.changed = True
- self.output.append("Create jump rule for chain %s" % self.chain)
- else:
- try:
- cmd = self.cmd + ['-L', self.jump_rule_chain, '--line-numbers']
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
-
- # break the input rules into rows and columns
- input_rules = [s.split() for s in to_native(output).split('\n')]
-
- # Find the last numbered rule
- last_rule_num = None
- last_rule_target = None
- for rule in input_rules[:-1]:
- if rule:
- try:
- last_rule_num = int(rule[0])
- except ValueError:
- continue
- last_rule_target = rule[1]
-
- # Naively assume that if the last row is a REJECT or DROP rule,
- # then we can insert our rule right before it, otherwise we
- # assume that we can just append the rule.
- if (last_rule_num and last_rule_target and last_rule_target in ['REJECT', 'DROP']):
- # insert rule
- cmd = self.cmd + ['-I', self.jump_rule_chain,
- str(last_rule_num)]
- else:
- # append rule
- cmd = self.cmd + ['-A', self.jump_rule_chain]
- cmd += ['-j', self.chain]
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
- self.changed = True
- self.output.append(output)
- self.save()
- except subprocess.CalledProcessError as ex:
- if '--line-numbers' in ex.cmd:
- raise IpTablesCreateJumpRuleError(
- chain=self.chain,
- msg=("Failed to query existing " +
- self.jump_rule_chain +
- " rules to determine jump rule location"),
- cmd=ex.cmd, exit_code=ex.returncode,
- output=ex.output)
- else:
- raise IpTablesCreateJumpRuleError(
- chain=self.chain,
- msg=("Failed to create jump rule for chain " +
- self.chain),
- cmd=ex.cmd, exit_code=ex.returncode,
- output=ex.output)
-
- def create_chain(self):
- if self.check_mode:
- self.changed = True
- self.output.append("Create chain %s" % self.chain)
- else:
- try:
- cmd = self.cmd + ['-N', self.chain]
- self.output.append(subprocess.check_output(cmd, stderr=subprocess.STDOUT))
- self.changed = True
- self.output.append("Successfully created chain %s" %
- self.chain)
- self.save()
- except subprocess.CalledProcessError as ex:
- raise IpTablesCreateChainError(
- chain=self.chain,
- msg="Failed to create chain: %s" % self.chain,
- cmd=ex.cmd, exit_code=ex.returncode, output=ex.output
- )
-
- def jump_rule_exists(self):
- cmd = self.cmd + ['-C', self.jump_rule_chain, '-j', self.chain]
- return True if subprocess.call(cmd) == 0 else False
-
- def chain_exists(self):
- cmd = self.cmd + ['-L', self.chain]
- return True if subprocess.call(cmd) == 0 else False
-
- def gen_cmd(self):
- cmd = 'iptables' if self.ip_version == 'ipv4' else 'ip6tables'
- # Include -w (wait for xtables lock) in default arguments.
- default_args = ['-w']
- return ["/usr/sbin/%s" % cmd] + default_args
-
- def gen_save_cmd(self): # pylint: disable=no-self-use
- return ['/usr/libexec/iptables/iptables.init', 'save']
-
-
-def main():
- module = AnsibleModule( # noqa: F405
- argument_spec=dict(
- name=dict(required=True),
- action=dict(required=True, choices=['add', 'remove',
- 'verify_chain']),
- chain=dict(required=False, default='OS_FIREWALL_ALLOW'),
- create_jump_rule=dict(required=False, type='bool', default=True),
- jump_rule_chain=dict(required=False, default='INPUT'),
- protocol=dict(required=False, choices=['tcp', 'udp']),
- port=dict(required=False, type='str'),
- ip_version=dict(required=False, default='ipv4',
- choices=['ipv4', 'ipv6']),
- ),
- supports_check_mode=True
- )
-
- action = module.params['action']
- protocol = module.params['protocol']
- port = module.params['port']
-
- if action in ['add', 'remove']:
- if not protocol:
- error = "protocol is required when action is %s" % action
- module.fail_json(msg=error)
- if not port:
- error = "port is required when action is %s" % action
- module.fail_json(msg=error)
-
- iptables_manager = IpTablesManager(module)
-
- try:
- if action == 'add':
- iptables_manager.add_rule(port, protocol)
- elif action == 'remove':
- iptables_manager.remove_rule(port, protocol)
- elif action == 'verify_chain':
- iptables_manager.verify_chain()
- except IpTablesError as ex:
- module.fail_json(msg=ex.msg)
-
- return module.exit_json(changed=iptables_manager.changed,
- output=iptables_manager.output)
-
-
-# pylint: disable=redefined-builtin, unused-wildcard-import, wildcard-import, wrong-import-position
-# import module snippets
-from ansible.module_utils.basic import * # noqa: F403,E402
-from ansible.module_utils._text import to_native # noqa: E402
-if __name__ == '__main__':
- main()
diff --git a/roles/os_firewall/tasks/firewall/firewalld.yml b/roles/os_firewall/tasks/firewall/firewalld.yml
index 509655b0c..2cc7af478 100644
--- a/roles/os_firewall/tasks/firewall/firewalld.yml
+++ b/roles/os_firewall/tasks/firewall/firewalld.yml
@@ -49,19 +49,3 @@
until: pkaction.rc == 0
retries: 6
delay: 10
-
-- name: Add firewalld allow rules
- firewalld:
- port: "{{ item.port }}"
- permanent: true
- immediate: true
- state: enabled
- with_items: "{{ os_firewall_allow }}"
-
-- name: Remove firewalld allow rules
- firewalld:
- port: "{{ item.port }}"
- permanent: true
- immediate: true
- state: disabled
- with_items: "{{ os_firewall_deny }}"
diff --git a/roles/os_firewall/tasks/firewall/iptables.yml b/roles/os_firewall/tasks/firewall/iptables.yml
index 55f2fc471..ccb3c4713 100644
--- a/roles/os_firewall/tasks/firewall/iptables.yml
+++ b/roles/os_firewall/tasks/firewall/iptables.yml
@@ -33,19 +33,3 @@
- name: need to pause here, otherwise the iptables service starting can sometimes cause ssh to fail
pause: seconds=10
when: result | changed
-
-- name: Add iptables allow rules
- os_firewall_manage_iptables:
- name: "{{ item.service }}"
- action: add
- protocol: "{{ item.port.split('/')[1] }}"
- port: "{{ item.port.split('/')[0] }}"
- with_items: "{{ os_firewall_allow }}"
-
-- name: Remove iptables rules
- os_firewall_manage_iptables:
- name: "{{ item.service }}"
- action: remove
- protocol: "{{ item.port.split('/')[1] }}"
- port: "{{ item.port.split('/')[0] }}"
- with_items: "{{ os_firewall_deny }}"