
    VhXW                         d dl mZmZmZ eZdZdZdZd dl	Z	d dl
Z
d dlZd dlZd dlZd dlZd dlmZ d dlmZmZ  edd	
      Z edd
      Z edd
      Zg dZd Zd Zd Zd Zd Zd Zedk(  r e        yy)    )absolute_importdivisionprint_functiona  
module: iptables_state
short_description: Save iptables state into a file or restore it from a file
version_added: '1.1.0'
author: quidame (@quidame)
extends_documentation_fragment:
  - community.general.attributes
  - community.general.attributes.flow
description:
  - C(iptables) is used to set up, maintain, and inspect the tables of IP packet filter rules in the Linux kernel.
  - This module handles the saving and/or loading of rules. This is the same as the behaviour of the C(iptables-save) and
    C(iptables-restore) (or C(ip6tables-save) and C(ip6tables-restore) for IPv6) commands which this module uses internally.
  - Modifying the state of the firewall remotely may lead to loose access to the host in case of mistake in new ruleset. This
    module embeds a rollback feature to avoid this, by telling the host to restore previous rules if a cookie is still there
    after a given delay, and all this time telling the controller to try to remove this cookie on the host through a new connection.
notes:
  - The rollback feature is not a module option and depends on task's attributes. To enable it, the module must be played
    asynchronously, in other words by setting task attributes C(poll) to V(0), and C(async) to a value less or equal to C(ANSIBLE_TIMEOUT).
    If C(async) is greater, the rollback will still happen if it shall happen, but you will experience a connection timeout
    instead of more relevant info returned by the module after its failure.
attributes:
  check_mode:
    support: full
  diff_mode:
    support: none
  action:
    support: full
  async:
    support: full
options:
  counters:
    description:
      - Save or restore the values of all packet and byte counters.
      - When V(true), the module is not idempotent.
    type: bool
    default: false
  ip_version:
    description:
      - Which version of the IP protocol this module should apply to.
    type: str
    choices: [ipv4, ipv6]
    default: ipv4
  modprobe:
    description:
      - Specify the path to the C(modprobe) program internally used by iptables related commands to load kernel modules.
      - By default, V(/proc/sys/kernel/modprobe) is inspected to determine the executable's path.
    type: path
  noflush:
    description:
      - For O(state=restored), ignored otherwise.
      - If V(false), restoring iptables rules from a file flushes (deletes) all previous contents of the respective table(s).
        If V(true), the previous rules are left untouched (but policies are updated anyway, for all built-in chains).
    type: bool
    default: false
  path:
    description:
      - The file the iptables state should be saved to.
      - The file the iptables state should be restored from.
    type: path
    required: true
  state:
    description:
      - Whether the firewall state should be saved (into a file) or restored (from a file).
    type: str
    choices: [saved, restored]
    required: true
  table:
    description:
      - When O(state=restored), restore only the named table even if the input file contains other tables. Fail if the named
        table is not declared in the file.
      - When O(state=saved), restrict output to the specified table. If not specified, output includes all active tables.
    type: str
    choices: [filter, nat, mangle, raw, security]
  wait:
    description:
      - Wait N seconds for the xtables lock to prevent instant failure in case multiple instances of the program are running
        concurrently.
    type: int
requirements: [iptables, ip6tables]
a  
# This will apply to all loaded/active IPv4 tables.
- name: Save current state of the firewall in system file
  community.general.iptables_state:
    state: saved
    path: /etc/sysconfig/iptables

# This will apply only to IPv6 filter table.
- name: save current state of the firewall in system file
  community.general.iptables_state:
    ip_version: ipv6
    table: filter
    state: saved
    path: /etc/iptables/rules.v6

# This will load a state from a file, with a rollback in case of access loss
- name: restore firewall state from a file
  community.general.iptables_state:
    state: restored
    path: /run/iptables.apply
  async: "{{ ansible_timeout }}"
  poll: 0

# This will load new rules by appending them to the current ones
- name: restore firewall state from a file
  community.general.iptables_state:
    state: restored
    path: /run/iptables.apply
    noflush: true
  async: "{{ ansible_timeout }}"
  poll: 0

# This will only retrieve information
- name: get current state of the firewall
  community.general.iptables_state:
    state: saved
    path: /tmp/iptables
  check_mode: true
  changed_when: false
  register: iptables_state

- name: show current state of the firewall
  ansible.builtin.debug:
    var: iptables_state.initial_state
a  
applied:
  description: Whether or not the wanted state has been successfully restored.
  type: bool
  returned: always
  sample: true
initial_state:
  description: The current state of the firewall when module starts.
  type: list
  elements: str
  returned: always
  sample:
    [
      "# Generated by xtables-save v1.8.2",
      "*filter",
      ":INPUT ACCEPT [0:0]",
      ":FORWARD ACCEPT [0:0]",
      ":OUTPUT ACCEPT [0:0]",
      "COMMIT",
      "# Completed"
    ]
restored:
  description: The state the module restored, whenever it is finally applied or not.
  type: list
  elements: str
  returned: always
  sample:
    [
      "# Generated by xtables-save v1.8.2",
      "*filter",
      ":INPUT DROP [0:0]",
      ":FORWARD DROP [0:0]",
      ":OUTPUT ACCEPT [0:0]",
      "-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT",
      "-A INPUT -m conntrack --ctstate INVALID -j DROP",
      "-A INPUT -i lo -j ACCEPT",
      "-A INPUT -p icmp -j ACCEPT",
      "-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT",
      "COMMIT",
      "# Completed"
    ]
saved:
  description: The iptables state the module saved.
  type: list
  elements: str
  returned: always
  sample:
    [
      "# Generated by xtables-save v1.8.2",
      "*filter",
      ":INPUT ACCEPT [0:0]",
      ":FORWARD DROP [0:0]",
      ":OUTPUT ACCEPT [0:0]",
      "COMMIT",
      "# Completed"
    ]
tables:
  description:
    - The iptables on the system before the module has run, separated by table.
    - If the option O(table) is used, only this table is included.
  type: dict
  contains:
    table:
      description: Policies and rules for all chains of the named table.
      type: list
      elements: str
  sample: |-
    {
      "filter": [
        ":INPUT ACCEPT",
        ":FORWARD ACCEPT",
        ":OUTPUT ACCEPT",
        "-A INPUT -i lo -j ACCEPT",
        "-A INPUT -p icmp -j ACCEPT",
        "-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT",
        "-A INPUT -j REJECT --reject-with icmp-host-prohibited"
      ],
      "nat": [
        ":PREROUTING ACCEPT",
        ":INPUT ACCEPT",
        ":OUTPUT ACCEPT",
        ":POSTROUTING ACCEPT"
      ]
    }
  returned: always
N)AnsibleModule)to_bytes	to_nativeiptables	ip6tables)ipv4ipv6ziptables-savezip6tables-saveziptables-restorezip6tables-restore)filtermanglenatrawsecurityc                     t        | d      5 }|j                         }ddd       j                         D cg c]
  }|dk7  s	| c}S # 1 sw Y   -xY wc c}w )zD
    Read a file and store its content in a variable as a list.
    rN )openread
splitlines)b_pathftextts       t/home/dcms/DCMS/lib/python3.12/site-packages/ansible_collections/community/general/plugins/modules/iptables_state.py
read_stater      sP     
fc	 avvx(4!AGA44 4s   A

AA
Ac           	         t        j                         \  }}t        j                  |d      5 }|j	                  dj                  dj                  |                   ddd       t        j                  j                  |       svt        j                  j                  |       }t        |d      }|rEt        j                  j                  |      s&t        j                  s	 t        j                  |       d
}nt!        j"                  ||       sd
}|r)t        j                  s	 t%        j&                  ||        |S |S # 1 sw Y   xY w# t        $ r0}t        j                  d|dt        |      |	       Y d}~d}~ww xY w# t        $ r>}t        | d      }	t        j                  d|	dt        |      |	       Y d}~|S d}~ww xY w)zL
    Write given contents to the given path, and return changed status.
    w{0}

Nsurrogate_or_stricterrorszError creating z: )msginitial_stateTzError saving state into )tempfilemkstemposfdopenwriteformatjoinpathexistsdirnamer   module
check_modemakedirs	Exception	fail_jsonfilecmpcmpshutilcopyfile)
r   lineschangedtmpfdtmpfiler   	b_destdirdestdirerrr.   s
             r   write_staterA   	  s~   
 %%'NE7	5#	 2!	tyy/012 77>>&!GGOOF+	I.CDRWW^^I6v?P?P)I&
 [[&) v((	%OOGV, N7N;2 2  )  3:IcNK"' ! ) ))  	%V,ABD8<inM#  % % N	%s;   0E #E &F  E		F&F  F	G3G

Gc                 6   |d}t        |       }|d|gz  }t        j                  |d      }t        j                  |d      \  }}}d|z  |j                         vr8d|z  }	t        j                  ||	d      }t        j                  |d      \  }}}|||fS )z
    This ensures iptables-state output is suitable for iptables-restore to roll
    back to it, i.e. iptables-save output is not empty. This also works for the
    iptables-nft-save alternative.
    r   z-tTcheck_rc*%sz*%s
:OUTPUT ACCEPT
COMMIT
)datarD   )listr1   run_commandr   )
initializerinitcommandfallbackcmdtablecommandlinedummyrcoutr@   iptables_inputs
             r   initialize_from_null_staterR   /  s     }{#KD%= K{T:E''d'CNRcu}CNN,,85@"";^d"S++K$+GS#sC<    c                     t        j                  dd|       } t        j                  d   st        j                  dd|       } | j	                         D cg c]
  }|dk7  s	| }}|S c c}w )z
    Remove timestamps to ensure idempotence between runs. Also remove counters
    by default. And return the result as a list.
    z/((^|\n)# (Generated|Completed)[^\n]*) on [^\n]*z\1countersz\[[0-9]+:[0-9]+\]z[0:0]r   )resubr1   paramsr   )stringliner:   s      r   filter_and_format_stater[   E  sc    
 VVFvVF==$,h?$//1@dTRZT@E@L As   
A'A'c                    t        |       }t               }d}t               }|D ]X  }t        j                  d|      r|dd }|dk(  r|||<   d}t               }6|j                  d      rH|j                  |       Z |S )z
    Convert raw iptables-save output into usable datastructure, for reliable
    comparisons between initial and final states.
    r   z%^[*](filter|mangle|nat|raw|security)$   NCOMMITz# )r[   dictrG   rV   match
startswithappend)all_states_dumpr:   tablescurrent_tablecurrent_listrZ   s         r   parse_per_table_staterg   Q  s    
 $O4EVFM6L "88<dC HM8$0F=!M6L??4 D!" MrS   c                     t        t        t        dd      t        dddgd      t        dg d	      t        d
d      t        d
d      t        d      t        dddgd      t        d      t        d      t        d      
      ddggd      at        dd      t        _        t        j                  d   } t        j                  d   }t        j                  d   }t        j                  d   }t        j                  d   }t        j                  d   }t        j                  d   }t        j                  d   }t        j                  d   }t        j                  d   }	t        j                  t        |   d      }
t        j                  t        |   d      }t        j                  t        |   d      }t        j                  d       d}g }|g}|
d d!g}|d"g}|g}|r|j                  d#       ||j                  d$|g       ||j                  d%d&|z  g       |Vt        |d'(      }t        j                  j                  |      st        j!                  d)|z  *       t        j                  j#                  |      st        j!                  d+|z  *       t        j$                  |t        j&                        st        j!                  d,|z  *       t        j$                  |t        j(                        st        j!                  d-|z  *       |j                  d.|g       |j                  d.|g       |j                  d.|g       |j                  d.|g       |j                  d.|g       t+        |      }|j-                  d/|       t        | d'(      }|dk(  rt        j                  j                  |      st        j!                  d0| z  *       t        j                  j#                  |      st        j!                  d1| z  *       t        j$                  |t        j&                        st        j!                  d2| z  *       t/        |      }d }nd3j1                  |      }t        j3                  |d4      \  }}}|p|dk(  rJt4        D ]@  }d5|z  v st7        |      d/k(  sd5|z  |j9                         vs/t;        ||||      \  }}}B nt7        |      d/k(  rqt;        |||d6      \  }}}n^|dk(  r$d5|z  vrt        j!                  d7|d8| *       n5t7        |      d/k(  sd5|z  |j9                         vrt;        ||||      \  }}}t=        |      }|t        j!                  d9*       t        j3                  |d4      \  }}}t?        |      }t=        |      }|dk(  r'tA        |||      }t        jC                  |||||:       t+        |      }|j-                  d/|       ||j                  d%d&|z  g       |	6t        |	d'(      } tA        | ||      }!t+        |      }"|"j                  |	       |r|j                  d;       |j                  |        d3j1                  |      }t+        |      }|j-                  d<d"       d=| d>t        j                  jE                  |      }#|D ]t  }t+        |      }$|$j                  d$|g       t        j3                  |$      \  }}}d?|v r|}#|d/k7  sFd3j1                  |$      }t        j!                  |#||||||d@	       v t        jF                  rtI        jJ                         \  }%}&t        jL                  |%dA      5 }'|'jO                  dBjQ                  dCj1                  |                   d d d        tS        jT                  |&|      r|}(n}(n|	\t        dD|	z  d'(      })	 t        j                  j                  |)      rt        jV                  |)       ntY        jZ                  dE       Kt        j3                  |      \  }}}d?|v rt        j!                  |||||||d@	       t        j3                  |d4      \  }}}t=        |      }(t?        dCj1                  |(            }*|(||fvr,|*j]                         D ]  \  }+},|+|vrd} n||+   |,k7  sd} n |	t        jF                  rt        jC                  |||||(dF       t_        |      D ]R  }!t        j                  j                         rtY        jZ                  d<       8t        jC                  |||||(dF       T t        j3                  "d4      \  }}}t        jV                          t        j3                  |d4      \  }}}t?        |      }-dG| dH|dI}.t        j!                  ||-k7  |.||||(dJ       y # 1 sw Y   =xY w)KNr.   T)typerequiredstrsavedrestored)ri   choicesrj   )r   r   r   r   r   )ri   rn   boolF)ri   default)ri   r   r   )ri   rn   rp   int)
r.   staterL   noflushrU   modprobe
ip_versionwait_timeout_backrw   rx   )argument_specrequired_togethersupports_check_modeC)LANGLC_MESSAGESrr   rL   rs   rU   rt   ru   rv   ?   z-Lz-nz--testz
--countersz--tablez--waitz%sr"   r#   zmodprobe %s not found)r%   zmodprobe %s not a filezmodprobe %s not readablezmodprobe %s not executablez
--modprober   zSource %s not foundzSource %s not a filezSource %s not readable rC   rE   r   zTable z to restore not defined in z.Unable to initialize firewall from NULL state.)r;   cmdrd   r&   rl   z	--noflushr]   zSource z is not suitable for input to z1Another app is currently holding the xtables lock)	r%   r   rO   stdoutstderrrd   r&   rm   appliedr   r    r!   z
%s.starterg{Gz?)r;   r   rd   r&   rm   r   z&Failed to confirm state restored from z after z6s. Firewall has been rolled back to its initial state.)r;   r%   r   rd   r&   rm   r   )0r   r_   r1   run_command_environ_updaterX   get_bin_pathIPTABLESSAVERESTOREr)   umaskrb   extendr   r.   r/   r5   isfileaccessR_OKX_OKrG   insertr   r-   rH   TABLESlenr   rR   r[   rg   rA   	exit_jsonbasenamer2   r'   r(   r*   r+   r,   r6   r7   removetimesleepitemsrange)/r.   rr   rL   rs   rU   rt   ru   rv   rw   rx   bin_iptablesbin_iptables_savebin_iptables_restorer;   COMMANDARGSINITCOMMANDINITIALIZERTESTCOMMANDFALLBACKCMD
b_modprobeSAVECOMMANDr   state_to_restorer   rO   r   r   r   r&   tables_beforeinitref_stateMAINCOMMANDb_backrN   BACKCOMMAND	error_msgtestcommandr<   r=   r   restored_state	b_startertables_after
table_nametable_contenttables_rollbackr%   s/                                                  r   mainr   i  s	    6D1EGZ+@4PE+YZfe4vu5v&0@&Q5!u%F#
 !
 !!F( )-#3(GF%== DMM'"EMM'"EmmI&G}}Z(H}}Z(H|,J== D}}Z(HMM'"E&&x
';TBL++D,<dC!..wz/BDIHHUOGK$%Kt,K'2K'(K<(Iu-.HdTk23h/DE
ww~~j)!88!CDww~~j)!9H!DEyyRWW-!;h!FGyyRWW-!=!HIL(34L(34L(34L(34L(34{#Kq+,d#89F
ww~~f%!6!=>ww~~f%!7$!>?yy)!9D!@A%f-hh{#!--kD-IR }J t19 006{a'519F<M<M<O+O/I+Wbdoqr/s,VVt [A#=k;Xcem#n R	*	6F!FtTU	V	UU]&2C2C2EE9+{T_afgVV+F3MMN "--kD-IR)&1M+F3MfmW= ' 	 	! {#Kq./HdTk23%(=>FM7;;'5!;'t
((;
C{#Kq(#?CRWWEUEUVjEklI  ;'Iq>*%11+>VV>&HI7((;'C$+)  	* !))+wYYuc" 	>aGGGNN499]#;<=	> ;;w'*N-N
  !5>STI77>>),IIi(

4 	   &11+>VV>&H$+)  	  &11+1MVV08(>)BCLm];;)5););)= 	%J.Z(M9	 })) '# 	 	* x 
77>>&!JJqM '# 	 		
 "--kD-IRIIf!--kD-IR+F3O BFx	Q 
 /1#  }	> 	>s   0g..g8__main__) 
__future__r   r   r   ri   __metaclass__DOCUMENTATIONEXAMPLESRETURNrV   r)   r   r'   r6   r8   ansible.module_utils.basicr   +ansible.module_utils.common.text.convertersr   r   r_   r   r   r   r   r   rA   rR   r[   rg   r   __name__ rS   r   <module>r      s    A @Ob,\U
p 
 	     4 K 		
 		
 		
 
85#L,	0`F	 zF rS   