diff --git a/lib/ansible/modules/extras/cloud/cloudstack/cs_firewall.py b/lib/ansible/modules/extras/cloud/cloudstack/cs_firewall.py
index d47f9b0ff6..e1e0f4a503 100644
--- a/lib/ansible/modules/extras/cloud/cloudstack/cs_firewall.py
+++ b/lib/ansible/modules/extras/cloud/cloudstack/cs_firewall.py
@@ -28,20 +28,35 @@ author: '"René Moser (@resmo)" <mail@renemoser.net>'
 options:
   ip_address:
     description:
-      - Public IP address the rule is assigned to.
-    required: true
+      - Public IP address the ingress rule is assigned to.
+      - Required if C(type=ingress).
+    required: false
+    default: null
+  network:
+    description:
+      - Network the egress rule is related to.
+      - Required if C(type=egress).
+    required: false
+    default: null
   state:
     description:
       - State of the firewall rule.
     required: false
     default: 'present'
     choices: [ 'present', 'absent' ]
+  type:
+    description:
+      - Type of the firewall rule.
+    required: false
+    default: 'ingress'
+    choices: [ 'ingress', 'egress' ]
   protocol:
     description:
       - Protocol of the firewall rule.
+      - C(all) is only available if C(type=egress)
     required: false
     default: 'tcp'
-    choices: [ 'tcp', 'udp', 'icmp' ]
+    choices: [ 'tcp', 'udp', 'icmp', 'all' ]
   cidr:
     description:
       - CIDR (full notation) to be used for firewall rule.
@@ -83,6 +98,11 @@ options:
       - Name of the project the firewall rule is related to.
     required: false
     default: null
+  poll_async:
+    description:
+      - Poll async jobs until job has finished.
+    required: false
+    default: true
 extends_documentation_fragment: cloudstack
 '''
 
@@ -114,15 +134,37 @@ EXAMPLES = '''
     end_port: 8888
     cidr: 17.0.0.0/8
     state: absent
+
+
+# Allow all outbound traffic
+- local_action:
+    module: cs_firewall
+    network: my_network
+    type: egress
+    protocol: all
+
+
+# Allow only HTTP outbound traffic for an IP
+- local_action:
+    module: cs_firewall
+    network: my_network
+    type: egress
+    port: 80
+    cidr: 10.101.1.20
 '''
 
 RETURN = '''
 ---
 ip_address:
-  description: IP address of the rule.
+  description: IP address of the rule if C(type=ingress)
   returned: success
   type: string
   sample: 10.100.212.10
+type:
+  description: Type of the rule.
+  returned: success
+  type: string
+  sample: ingress
 cidr:
   description: CIDR of the rule.
   returned: success
@@ -153,6 +195,11 @@ icmp_type:
   returned: success
   type: int
   sample: 1
+network:
+  description: Name of the network if C(type=egress)
+  returned: success
+  type: string
+  sample: my_network
 '''
 
 try:
@@ -180,32 +227,46 @@ class AnsibleCloudStackFirewall(AnsibleCloudStack):
 
     def get_firewall_rule(self):
         if not self.firewall_rule:
-            cidr = self.module.params.get('cidr')
-            protocol = self.module.params.get('protocol')
-            start_port = self.module.params.get('start_port')
-            end_port = self.get_end_port()
-            icmp_code = self.module.params.get('icmp_code')
-            icmp_type = self.module.params.get('icmp_type')
+            cidr        = self.module.params.get('cidr')
+            protocol    = self.module.params.get('protocol')
+            start_port  = self.module.params.get('start_port')
+            end_port    = self.get_end_port()
+            icmp_code   = self.module.params.get('icmp_code')
+            icmp_type   = self.module.params.get('icmp_type')
+            fw_type     = self.module.params.get('type')
 
             if protocol in ['tcp', 'udp'] and not (start_port and end_port):
-                self.module.fail_json(msg="no start_port or end_port set for protocol '%s'" % protocol)
+                self.module.fail_json(msg="missing required argument for protocol '%s': start_port or end_port" % protocol)
 
             if protocol == 'icmp' and not icmp_type:
-                self.module.fail_json(msg="no icmp_type set")
+                self.module.fail_json(msg="missing required argument for protocol 'icmp': icmp_type")
+
+            if protocol == 'all' and fw_type != 'egress':
+                self.module.fail_json(msg="protocol 'all' could only be used for type 'egress'" )
 
             args                = {}
-            args['ipaddressid'] = self.get_ip_address('id')
             args['account']     = self.get_account('name')
             args['domainid']    = self.get_domain('id')
             args['projectid']   = self.get_project('id')
 
-            firewall_rules = self.cs.listFirewallRules(**args)
+            if fw_type == 'egress':
+                args['networkid'] = self.get_network(key='id')
+                if not args['networkid']:
+                    self.module.fail_json(msg="missing required argument for type egress: network")
+                firewall_rules = self.cs.listEgressFirewallRules(**args)
+            else:
+                args['ipaddressid'] = self.get_ip_address('id')
+                if not args['ipaddressid']:
+                    self.module.fail_json(msg="missing required argument for type ingress: ip_address")
+                firewall_rules = self.cs.listFirewallRules(**args)
+
             if firewall_rules and 'firewallrule' in firewall_rules:
                 for rule in firewall_rules['firewallrule']:
                     type_match = self._type_cidr_match(rule, cidr)
 
                     protocol_match = self._tcp_udp_match(rule, protocol, start_port, end_port) \
-                        or self._icmp_match(rule, protocol, icmp_code, icmp_type)
+                        or self._icmp_match(rule, protocol, icmp_code, icmp_type) \
+                        or self._egress_all_match(rule, protocol, fw_type)
 
                     if type_match and protocol_match:
                         self.firewall_rule = rule
@@ -220,6 +281,12 @@ class AnsibleCloudStackFirewall(AnsibleCloudStack):
             and end_port == int(rule['endport'])
 
 
+    def _egress_all_match(self, rule, protocol, fw_type):
+        return protocol in ['all'] \
+            and protocol == rule['protocol'] \
+            and fw_type == 'egress'
+
+
     def _icmp_match(self, rule, protocol, icmp_code, icmp_type):
         return protocol == 'icmp' \
            and protocol == rule['protocol'] \
@@ -231,6 +298,30 @@ class AnsibleCloudStackFirewall(AnsibleCloudStack):
         return cidr == rule['cidrlist']
 
 
+    def get_network(self, key=None, network=None):
+        if not network:
+            network = self.module.params.get('network')
+
+        if not network:
+            return None
+
+        args                = {}
+        args['account']     = self.get_account('name')
+        args['domainid']    = self.get_domain('id')
+        args['projectid']   = self.get_project('id')
+        args['zoneid']      = self.get_zone('id')
+
+        networks = self.cs.listNetworks(**args)
+        if not networks:
+            self.module.fail_json(msg="No networks available")
+
+        for n in networks['network']:
+            if network in [ n['displaytext'], n['name'], n['id'] ]:
+                return self._get_by_key(key, n)
+                break
+        self.module.fail_json(msg="Network '%s' not found" % network)
+
+
     def create_firewall_rule(self):
         firewall_rule = self.get_firewall_rule()
         if not firewall_rule:
@@ -243,11 +334,22 @@ class AnsibleCloudStackFirewall(AnsibleCloudStack):
             args['endport']     = self.get_end_port()
             args['icmptype']    = self.module.params.get('icmp_type')
             args['icmpcode']    = self.module.params.get('icmp_code')
-            args['ipaddressid'] = self.get_ip_address('id')
 
+            fw_type = self.module.params.get('type')
             if not self.module.check_mode:
-                firewall_rule = self.cs.createFirewallRule(**args)
+                if fw_type == 'egress':
+                    args['networkid'] = self.get_network(key='id')
+                    res = self.cs.createEgressFirewallRule(**args)
+                else:
+                    args['ipaddressid'] = self.get_ip_address('id')
+                    res = self.cs.createFirewallRule(**args)
 
+                if 'errortext' in res:
+                    self.module.fail_json(msg="Failed: '%s'" % res['errortext'])
+
+                poll_async = self.module.params.get('poll_async')
+                if poll_async:
+                     firewall_rule = self._poll_job(res, 'firewallrule')
         return firewall_rule
 
 
@@ -255,17 +357,29 @@ class AnsibleCloudStackFirewall(AnsibleCloudStack):
         firewall_rule = self.get_firewall_rule()
         if firewall_rule:
             self.result['changed'] = True
-            args = {}
+
+            args       = {}
             args['id'] = firewall_rule['id']
 
+            fw_type = self.module.params.get('type')
             if not self.module.check_mode:
-                res = self.cs.deleteFirewallRule(**args)
+                if fw_type == 'egress':
+                    res = self.cs.deleteEgressFirewallRule(**args)
+                else:
+                    res = self.cs.deleteFirewallRule(**args)
 
+                if 'errortext' in res:
+                    self.module.fail_json(msg="Failed: '%s'" % res['errortext'])
+
+                poll_async = self.module.params.get('poll_async')
+                if poll_async:
+                     res = self._poll_job(res, 'firewallrule')
         return firewall_rule
 
 
     def get_result(self, firewall_rule):
         if firewall_rule:
+            self.result['type'] = self.module.params.get('type')
             if 'cidrlist' in firewall_rule:
                 self.result['cidr'] = firewall_rule['cidrlist']
             if 'startport' in firewall_rule:
@@ -280,15 +394,19 @@ class AnsibleCloudStackFirewall(AnsibleCloudStack):
                 self.result['icmp_code'] = int(firewall_rule['icmpcode'])
             if 'icmptype' in firewall_rule:
                 self.result['icmp_type'] = int(firewall_rule['icmptype'])
+            if 'networkid' in firewall_rule:
+                self.result['network'] = self.get_network(key='displaytext', network=firewall_rule['networkid'])
         return self.result
 
 
 def main():
     module = AnsibleModule(
         argument_spec = dict(
-            ip_address = dict(required=True),
+            ip_address = dict(default=None),
+            network = dict(default=None),
             cidr = dict(default='0.0.0.0/0'),
-            protocol = dict(choices=['tcp', 'udp', 'icmp'], default='tcp'),
+            protocol = dict(choices=['tcp', 'udp', 'icmp', 'all'], default='tcp'),
+            type = dict(choices=['ingress', 'egress'], default='ingress'),
             icmp_type = dict(type='int', default=None),
             icmp_code = dict(type='int', default=None),
             start_port = dict(type='int', aliases=['port'], default=None),
@@ -297,6 +415,7 @@ def main():
             domain = dict(default=None),
             account = dict(default=None),
             project = dict(default=None),
+            poll_async = dict(choices=BOOLEANS, default=True),
             api_key = dict(default=None),
             api_secret = dict(default=None, no_log=True),
             api_url = dict(default=None),
@@ -305,6 +424,7 @@ def main():
         mutually_exclusive = (
             ['icmp_type', 'start_port'],
             ['icmp_type', 'end_port'],
+            ['ip_address', 'network'],
         ),
         supports_check_mode=True
     )