- name: Gather Facts setup: - name: Generate password for the CA key shell: > < /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-12};echo; register: CA_password - set_fact: easyrsa_p12_export_password: "{{ (ansible_date_time.iso8601_basic|sha1|to_uuid).split('-')[0] }}" easyrsa_CA_password: "{{ CA_password.stdout }}" IP_subject_alt_name: "{{ IP_subject_alt_name }}" - name: Change the algorithm to RSA set_fact: algo_params: "rsa:2048" when: Win10_Enabled is defined and Win10_Enabled == "Y" - name: Install StrongSwan apt: name=strongswan state=latest update_cache=yes - name: Enforcing ipsec with apparmor shell: aa-enforce "{{ item }}" when: apparmor_enabled is defined and apparmor_enabled == true with_items: - /usr/lib/ipsec/charon - /usr/lib/ipsec/lookip - /usr/lib/ipsec/stroke notify: - restart apparmor tags: ['apparmor'] - name: Enable services service: name={{ item }} enabled=yes with_items: - apparmor - strongswan - netfilter-persistent - name: Configure iptables so IPSec traffic can traverse the tunnel iptables: table=nat chain=POSTROUTING source="{{ vpn_network }}" jump=MASQUERADE when: (security_enabled is not defined) or (security_enabled is defined and security_enabled != "y") notify: - save iptables - name: Configure ip6tables so IPSec traffic can traverse the tunnel iptables: ip_version=ipv6 table=nat chain=POSTROUTING source="{{ vpn_network_ipv6 }}" jump=MASQUERADE when: ((security_enabled is not defined) or (security_enabled is defined and security_enabled != "y")) and ipv6_support is defined and ipv6_support == "yes" notify: - save iptables - name: Ensure that the strongswan group exist group: name=strongswan state=present - name: Ensure that the strongswan user exist user: name=strongswan group=strongswan state=present - name: Ensure that the strongswan service directory exist file: path=/etc/systemd/system/strongswan.service.d/ state=directory mode=0755 owner=root group=root - name: Setup the cgroup limitations for the ipsec daemon template: src=100-CustomLimitations.conf.j2 dest=/etc/systemd/system/strongswan.service.d/100-CustomLimitations.conf notify: - daemon-reload - restart strongswan - meta: flush_handlers - name: Setup the strongswan.conf file from our template template: src=strongswan.conf.j2 dest=/etc/strongswan.conf owner=root group=root mode=0644 notify: - restart strongswan - name: Setup the ipsec.conf file from our template template: src=ipsec.conf.j2 dest=/etc/ipsec.conf owner=root group=root mode=0644 notify: - restart strongswan - name: Setup the ipsec.secrets file template: src=ipsec.secrets.j2 dest=/etc/ipsec.secrets owner=strongswan group=root mode=0600 notify: - restart strongswan - name: Get loaded plugins shell: > find /etc/strongswan.d/charon/ -type f -name '*.conf' -printf '%f\n' | cut -f1 -d. register: strongswan_plugins - name: Disable unneeded plugins lineinfile: dest="/etc/strongswan.d/charon/{{ item }}.conf" regexp='.*load.*' line='load = no' state=present notify: - restart strongswan when: item not in strongswan_enabled_plugins with_items: "{{ strongswan_plugins.stdout_lines }}" - name: Ensure that required plugins are enabled lineinfile: dest="/etc/strongswan.d/charon/{{ item }}.conf" regexp='.*load.*' line='load = yes' state=present notify: - restart strongswan when: item in strongswan_enabled_plugins with_items: "{{ strongswan_plugins.stdout_lines }}" - name: Ensure the pki directory is not exist local_action: module: file dest: configs/{{ IP_subject_alt_name }}/pki state: absent become: no when: easyrsa_reinit_existent == True - name: Ensure the pki directories are exist local_action: module: file dest: "configs/{{ IP_subject_alt_name }}/pki/{{ item }}" state: directory recurse: yes become: no with_items: - ecparams - certs - crl - newcerts - private - reqs - name: Ensure the files are exist local_action: module: file dest: "configs/{{ IP_subject_alt_name }}/pki/{{ item }}" state: touch become: no with_items: - ".rnd" - "private/.rnd" - "index.txt" - "index.txt.attr" - "serial" - name: Generate the openssl server configs local_action: module: template src: openssl.cnf.j2 dest: "configs/{{ IP_subject_alt_name }}/pki/openssl.cnf" become: no - name: Build the CA pair local_action: > shell openssl ecparam -name prime256v1 -out ecparams/prime256v1.pem && openssl req -utf8 -new -newkey {{ algo_params | default('ec:ecparams/prime256v1.pem') }} -config openssl.cnf -keyout private/cakey.pem -out cacert.pem -x509 -days 3650 -batch -passout pass:"{{ easyrsa_CA_password }}" && touch {{ IP_subject_alt_name }}_ca_generated become: no args: chdir: "configs/{{ IP_subject_alt_name }}/pki/" creates: "{{ IP_subject_alt_name }}_ca_generated" environment: subjectAltName: "DNS:{{ IP_subject_alt_name }},IP:{{ IP_subject_alt_name }}" - name: Copy the CA certificate local_action: module: copy src: "configs/{{ IP_subject_alt_name }}/pki/cacert.pem" dest: "configs/{{ IP_subject_alt_name }}/cacert.pem" mode: 0600 become: no - name: Generate the serial number local_action: > shell echo 01 > serial && touch serial_generated become: no args: chdir: "configs/{{ IP_subject_alt_name }}/pki/" creates: serial_generated - name: Build the server pair local_action: > shell openssl req -utf8 -new -newkey {{ algo_params | default('ec:ecparams/prime256v1.pem') }} -config openssl.cnf -keyout private/{{ IP_subject_alt_name }}.key -out reqs/{{ IP_subject_alt_name }}.req -nodes -passin pass:"{{ easyrsa_CA_password }}" -subj "/CN={{ IP_subject_alt_name }}" -batch && openssl ca -utf8 -in reqs/{{ IP_subject_alt_name }}.req -out certs/{{ IP_subject_alt_name }}.crt -config openssl.cnf -days 3650 -batch -passin pass:"{{ easyrsa_CA_password }}" -subj "/CN={{ IP_subject_alt_name }}" && touch certs/{{ IP_subject_alt_name }}_crt_generated become: no args: chdir: "configs/{{ IP_subject_alt_name }}/pki/" creates: certs/{{ IP_subject_alt_name }}_crt_generated environment: subjectAltName: "DNS:{{ IP_subject_alt_name }},IP:{{ IP_subject_alt_name }}" - name: Build the client's pair local_action: > shell openssl req -utf8 -new -newkey {{ algo_params | default('ec:ecparams/prime256v1.pem') }} -config openssl.cnf -keyout private/{{ item }}.key -out reqs/{{ item }}.req -nodes -passin pass:"{{ easyrsa_CA_password }}" -subj "/CN={{ item }}" -batch && openssl ca -utf8 -in reqs/{{ item }}.req -out certs/{{ item }}.crt -config openssl.cnf -days 3650 -batch -passin pass:"{{ easyrsa_CA_password }}" -subj "/CN={{ item }}" && touch certs/{{ item }}_crt_generated become: no args: chdir: "configs/{{ IP_subject_alt_name }}/pki/" creates: certs/{{ item }}_crt_generated environment: subjectAltName: "DNS:{{ item }}" with_items: "{{ users }}" - name: Build the client's p12 local_action: > shell openssl pkcs12 -in certs/{{ item }}.crt -inkey private/{{ item }}.key -export -name {{ item }} -out private/{{ item }}.p12 -certfile cacert.pem -passout pass:"{{ easyrsa_p12_export_password }}" become: no args: chdir: "configs/{{ IP_subject_alt_name }}/pki/" with_items: "{{ users }}" - name: Copy the p12 certificates local_action: module: copy src: "configs/{{ IP_subject_alt_name }}/pki/private/{{ item }}.p12" dest: "configs/{{ IP_subject_alt_name }}/{{ item }}.p12" mode: 0600 become: no with_items: - "{{ users }}" - name: Copy the CA cert to the strongswan directory copy: src='configs/{{ IP_subject_alt_name }}/pki/cacert.pem' dest=/etc/ipsec.d/cacerts/ca.crt owner=strongswan group=root mode=0600 notify: - restart strongswan - name: Copy the server cert to the strongswan directory copy: src='configs/{{ IP_subject_alt_name }}/pki/certs/{{ IP_subject_alt_name }}.crt' dest=/etc/ipsec.d/certs/{{ IP_subject_alt_name }}.crt owner=strongswan group=root mode=0600 notify: - restart strongswan - name: Copy the server key to the strongswan directory copy: src='configs/{{ IP_subject_alt_name }}/pki/private/{{ IP_subject_alt_name }}.key' dest=/etc/ipsec.d/private/{{ IP_subject_alt_name }}.key owner=strongswan group=root mode=0600 notify: - restart strongswan - name: Register p12 PayloadContent local_action: > shell cat private/{{ item }}.p12 | base64 register: PayloadContent become: no args: chdir: "configs/{{ IP_subject_alt_name }}/pki/" with_items: "{{ users }}" - name: Set facts for mobileconfigs set_fact: proxy_enabled: false PayloadContentCA: "{{ lookup('file' , 'configs/{{ IP_subject_alt_name }}/pki/cacert.pem')|b64encode }}" - name: Build the mobileconfigs local_action: module: template src: mobileconfig.j2 dest: configs/{{ IP_subject_alt_name }}/{{ item.0 }}.mobileconfig mode: 0600 become: no with_together: - "{{ users }}" - "{{ PayloadContent.results }}" no_log: True - name: Build the client ipsec config file local_action: module: template src: client_ipsec.conf.j2 dest: configs/{{ IP_subject_alt_name }}/ipsec_{{ item }}.conf mode: 0600 become: no with_items: - "{{ users }}" - name: Build the client ipsec secret file local_action: module: template src: client_ipsec.secrets.j2 dest: configs/{{ IP_subject_alt_name }}/ipsec_{{ item }}.secrets mode: 0600 become: no with_items: - "{{ users }}" - name: Build the windows client powershell script local_action: module: template src: client_windows.ps1.j2 dest: configs/{{ IP_subject_alt_name }}/windows_{{ item }}.ps1 mode: 0600 become: no when: Win10_Enabled is defined and Win10_Enabled == "Y" with_items: "{{ users }}" - name: Restrict permissions for the remote private directories file: path="{{ item }}" state=directory mode=0700 owner=strongswan group=root with_items: - /etc/ipsec.d/private - name: Restrict permissions for the local private directories local_action: module: file path: "{{ item }}" state: directory mode: 0700 become: no with_items: - configs/{{ IP_subject_alt_name }} - include: iptables.yml tags: iptables