From 5fbb82184807deebbd2d7a261450957d9ca5dec7 Mon Sep 17 00:00:00 2001 From: Dan Guido Date: Fri, 29 Jul 2016 22:21:33 -0400 Subject: [PATCH] Initial commit --- .gitignore | 4 + LICENSE | 21 ++++ README.md | 22 +++++ ansible.cfg | 4 + cloud.yml | 78 +++++++++++++++ common.yml | 96 ++++++++++++++++++ config.cfg | 28 ++++++ configs/.gitinit | 0 deploy.yml | 6 ++ inventory | 5 + inventory_users | 2 + security.yml | 134 +++++++++++++++++++++++++ templates/CIS.conf.j2 | 15 +++ templates/audit.rules.j2 | 101 +++++++++++++++++++ templates/auditd.conf.j2 | 32 ++++++ templates/easy-rsa.vars.j2 | 198 +++++++++++++++++++++++++++++++++++++ templates/ipsec.conf.j2 | 29 ++++++ templates/ipsec.secrets.j2 | 2 + templates/mobileconfig.j2 | 144 +++++++++++++++++++++++++++ templates/rsyslog.conf.j2 | 61 ++++++++++++ users.yml | 74 ++++++++++++++ vpn.yml | 150 ++++++++++++++++++++++++++++ 22 files changed, 1206 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 ansible.cfg create mode 100644 cloud.yml create mode 100644 common.yml create mode 100644 config.cfg create mode 100644 configs/.gitinit create mode 100644 deploy.yml create mode 100644 inventory create mode 100644 inventory_users create mode 100644 security.yml create mode 100644 templates/CIS.conf.j2 create mode 100644 templates/audit.rules.j2 create mode 100644 templates/auditd.conf.j2 create mode 100644 templates/easy-rsa.vars.j2 create mode 100644 templates/ipsec.conf.j2 create mode 100644 templates/ipsec.secrets.j2 create mode 100644 templates/mobileconfig.j2 create mode 100644 templates/rsyslog.conf.j2 create mode 100644 users.yml create mode 100644 vpn.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a309864 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.retry +configs/*.mobileconfig +configs/*.p12 +configs/*.crt diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7365a69 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Trail of Bits + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..ac3f38d --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +##### Local requirements: +* ansible >= 2.2.0 +* python >= 2.6 +* dopy + +##### How to run: +* Open the file `config.cfg` in your favorite text editor and change variables. At least you should change `server_name`, and specify users in `users` list. +* Start to deploy and follow the instructions: +``` +ansible-playbook deploy.yml +``` +* When the process is done, you can see `.mobileconfig` files and certificates in the directory - `configs`. Send `.mobileconfig` to your users for using on iPhones or MacOS or send certificates for using on other clients (StrongSwan client for Android or native IKEv2 client for Windows) + +* When the deploy proccess is done a new server will be placed in the local inventory file - `inventory_users` + +* If you want to add or delete users, just update the (`users`) list in the config file (`config.cfg`) and then run the playbook: +(This command will update users on all your servers in the file `inventory_users`, if you want to limit servers, you can use option `-l` ) +``` +ansible-playbook users.yml -i inventory_users +ansible-playbook users.yml -i inventory_users -l vpnserver.com +``` + diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..4d407ab --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,4 @@ +[defaults] +inventory = inventory +pipelining = True +retry_files_enabled = False diff --git a/cloud.yml b/cloud.yml new file mode 100644 index 0000000..db10f15 --- /dev/null +++ b/cloud.yml @@ -0,0 +1,78 @@ +- name: Configure the server and install required software + hosts: localhost + + vars: + regions: + "1": "ams2" + "2": "ams3" + "3": "fra1" + "4": "lon1" + "5": "nyc1" + "6": "nyc2" + "7": "nyc3" + "8": "sfo1" + "9": "sgp1" + "10": "tor1" + + vars_prompt: + - name: "do_access_token" + prompt: "Enter your API Token (https://cloud.digitalocean.com/settings/api/tokens):\n" + private: yes + + - name: "do_ssh_name" + prompt: "Enter a valid SSH key name (https://cloud.digitalocean.com/settings/security):\n" + private: no + + - name: "do_region" + prompt: > + What region should the server be located in? + 1. Amsterdam (Datacenter 2) + 2. Amsterdam (Datacenter 3) + 3. Frankfurt + 4. London + 5. New York (Datacenter 1) + 6. New York (Datacenter 2) + 7. New York (Datacenter 3) + 8. San Francisco + 9. Singapore + 10. Toronto + Please choose the number of your region. Press enter for default (#7) region. + default: "7" + private: no + + - name: "do_server_name" + prompt: "Name the vpn server:\n" + default: "strongswan.local" + private: no + + tasks: + - name: "Getting your SSH key ID on Digital Ocean..." + digital_ocean: + state: present + command: ssh + name: "{{ do_ssh_name }}" + api_token: "{{ do_access_token }}" + register: do_ssh_key + + - name: "Creating a droplet..." + digital_ocean: + state: present + command: droplet + name: "{{ do_server_name }}" + region_id: "{{ regions[do_region] }}" + size_id: "512mb" + image_id: "ubuntu-16-04-x64" + ssh_key_ids: "{{ do_ssh_key.ssh_key.id }}" + unique_name: yes + api_token: "{{ do_access_token }}" + register: do + + - name: Add the droplet to an inventory group + add_host: + name: "{{ do.droplet.ip_address }}" + groups: vpn-host + ansible_python_interpreter: "/usr/bin/python2.7" + + - name: Pause to let DigitalOcean boot up the VM + pause: seconds=180 + diff --git a/common.yml b/common.yml new file mode 100644 index 0000000..a567270 --- /dev/null +++ b/common.yml @@ -0,0 +1,96 @@ +--- + +- name: Common tools + hosts: vpn-host + remote_user: root + vars_files: + - config.cfg + + tasks: + - name: Wait for port 22 to become available + local_action: "wait_for port=22 host={{ inventory_hostname }}" + + - name: Updating apt-get + raw: apt-get update -qq + + - name: Install python2.7 for Ansible + raw: apt-get install -qq -y python2.7 + + - name: Install Updates, Patches and Additional Security Software + apt: upgrade=dist update_cache=yes + + - name: Check if reboot is required + shell: > + if [[ $(readlink -f /vmlinuz) != /boot/vmlinuz-$(uname -r) ]]; then echo "required"; else echo "no"; fi + args: + executable: /bin/bash + register: reboot_required + + - name: Reboot + shell: sleep 2 && shutdown -r now "Ansible updates triggered" + async: 1 + poll: 0 + when: reboot_required is defined and reboot_required.stdout == 'required' + ignore_errors: true + + - name: Wait for shutdown + local_action: wait_for host={{ inventory_hostname }} port=22 state=stopped timeout=120 + when: reboot_required is defined and reboot_required.stdout == 'required' + + - name: Wait until SSH becomes ready... + local_action: wait_for host={{ inventory_hostname }} port=22 state=started timeout=120 + when: reboot_required is defined and reboot_required.stdout == 'required' + + # SSH fixes + + - name: SSH config + lineinfile: dest="{{ item.file }}" regexp="{{ item.regexp }}" line="{{ item.line }}" state=present + with_items: + - { regexp: '^PasswordAuthentication.*', line: 'PasswordAuthentication no', file: '/etc/ssh/sshd_config' } + - { regexp: '^PermitRootLogin.*', line: 'PermitRootLogin without-password', file: '/etc/ssh/sshd_config' } + - { regexp: '^UseDNS.*', line: 'UseDNS no', file: '/etc/ssh/sshd_config' } + - { regexp: '^Ciphers', line: 'Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes128-ctr', file: '/etc/ssh/sshd_config' } + - { regexp: '^MACs', line: 'MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160', file: '/etc/ssh/sshd_config' } + - { regexp: '^KexAlgorithms', line: 'KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha1', file: '/etc/ssh/sshd_config' } + notify: + - restart ssh + + - name: PAM config + replace: dest="{{ item.file }}" regexp="{{ item.regexp }}" replace="{{ item.line }}" + with_items: + - { regexp: '^session.*optional.*pam_motd.so.*', line: '# MOTD DISABLED', file: '/etc/pam.d/login' } + - { regexp: '^session.*optional.*pam_motd.so.*', line: '# MOTD DISABLED', file: '/etc/pam.d/sshd' } + + - name: Install tools + apt: name="{{ item }}" state=latest + with_items: + - git + - screen + - apparmor-utils + - uuid-runtime + - coreutils + - auditd + - rsyslog + - sendmail + - unattended-upgrades + + - name: Unattended-upgrades configured + template: src=50unattended-upgrades.j2 dest=/etc/apt/apt.conf.d/50unattended-upgrades owner=root group=root mode=644 + + - name: Periodic upgrades configured + template: src=10periodic.j2 dest=/etc/apt/apt.conf.d/10periodic owner=root group=root mode=644 + + handlers: + - name: restart auditd + service: name=auditd state=restarted + + - name: restart rsyslog + service: name=rsyslog state=restarted + + - name: restart ssh + service: name=ssh state=restarted + + - name: flush routing cache + shell: echo 1 > /proc/sys/net/ipv4/route/flush + + \ No newline at end of file diff --git a/config.cfg b/config.cfg new file mode 100644 index 0000000..7b98fc5 --- /dev/null +++ b/config.cfg @@ -0,0 +1,28 @@ +--- + +# +# IKEv2 currently supports only the following three curves: +# prime256v1 +# secp384r1 +# secp521r1 +easyrsa_dir: /opt/easy-rsa-ipsec +easyrsa_ca_expire: 3650 +easyrsa_cert_expire: 3650 +easyrsa_p12_export_password: vpn + +# if True re-init all existing certificates. Boolean +easyrsa_reinit_existent: False + +# Domain or ip +server_name: www.ivlis.me +server_ip: "{{ ansible_ssh_host }}" + +users: + - mr.smith + - mrs.smith + +# +# auditd options +# email for auditd actions: +auditd_action_mail_acct: e601809@gmail.com + diff --git a/configs/.gitinit b/configs/.gitinit new file mode 100644 index 0000000..e69de29 diff --git a/deploy.yml b/deploy.yml new file mode 100644 index 0000000..44a2bd5 --- /dev/null +++ b/deploy.yml @@ -0,0 +1,6 @@ +--- + +- include: cloud.yml +- include: common.yml +- include: security.yml +- include: vpn.yml diff --git a/inventory b/inventory new file mode 100644 index 0000000..5b1a53f --- /dev/null +++ b/inventory @@ -0,0 +1,5 @@ +[localhost] +127.0.0.1 ansible_connection=local + +[vpn-host] +45.55.244.205 ansible_python_interpreter=/usr/bin/python2.7 diff --git a/inventory_users b/inventory_users new file mode 100644 index 0000000..4b3531e --- /dev/null +++ b/inventory_users @@ -0,0 +1,2 @@ +[users-management] +45.55.244.205 diff --git a/security.yml b/security.yml new file mode 100644 index 0000000..449645a --- /dev/null +++ b/security.yml @@ -0,0 +1,134 @@ +--- + +- name: Security fixes + hosts: vpn-host + remote_user: root + vars_files: + - config.cfg + + tasks: + # Using a two-pass approach for checking directories in order to support symlinks. + - name: Find directories for minimizing access + stat: + path: "{{ item }}" + register: minimize_access_directories + with_items: + - '/usr/local/sbin' + - '/usr/local/bin' + - '/usr/sbin' + - '/usr/bin' + - '/sbin' + - '/bin' + + - name: Minimize access + file: path='{{ item.stat.path }}' mode='go-w' recurse=yes + when: item.stat.isdir + with_items: "{{ minimize_access_directories.results }}" + no_log: True + + - name: Change shadow ownership to root and mode to 0600 + file: dest='/etc/shadow' owner=root group=root mode=0600 + + - name: change su-binary to only be accessible to user and group root + file: dest='/bin/su' owner=root group=root mode=0750 + + # auditd + + - name: Collect Use of Privileged Commands + shell: > + /usr/bin/find {/usr/local/sbin,/usr/local/bin,/sbin,/bin,/usr/sbin,/usr/bin} -xdev \( -perm -4000 -o -perm -2000 \) -type f | awk '{print "-a always,exit -F path=" $1 " -F perm=x -F auid>=500 -F auid!=4294967295 -k privileged" }' + args: + executable: /bin/bash + register: privileged_programs + + - name: Auditd rules configured + template: src=audit.rules.j2 dest=/etc/audit/audit.rules + notify: + - restart auditd + + - name: Auditd configured + template: src=auditd.conf.j2 dest=/etc/audit/auditd.conf + notify: + - restart auditd + + # Rsyslog + + - name: Rsyslog configured + template: src=rsyslog.conf.j2 dest=/etc/rsyslog.conf + notify: + - restart rsyslog + + - name: Rsyslog CIS configured + template: src=CIS.conf.j2 dest=/etc/rsyslog.d/CIS.conf owner=root group=root mode=0644 + notify: + - restart rsyslog + + - name: Enable services + service: name={{ item }} enabled=yes + with_items: + - auditd + - rsyslog + + # Core dumps + + - name: Restrict Core Dumps - using pam limits + lineinfile: dest=/etc/security/limits.conf line="* hard core 0" state=present + + - name: Restrict Core Dumps - using sysctl + sysctl: name=fs.suid_dumpable value=0 ignoreerrors=yes sysctl_set=yes reload=yes state=present + + # Kernel fixes + + - name: Disable Source Routed Packet Acceptance + sysctl: name="{{item}}" value=0 ignoreerrors=yes sysctl_set=yes reload=yes state=present + with_items: + - net.ipv4.conf.all.accept_source_route + - net.ipv4.conf.default.accept_source_route + notify: + - flush routing cache + + - name: Disable ICMP Redirect Acceptance + sysctl: name="{{item}}" value=0 ignoreerrors=yes sysctl_set=yes reload=yes state=present + with_items: + - net.ipv4.conf.all.accept_redirects + - net.ipv4.conf.default.accept_redirects + + - name: Disable Secure ICMP Redirect Acceptance + sysctl: name="{{item}}" value=0 ignoreerrors=yes sysctl_set=yes reload=yes state=present + with_items: + - net.ipv4.conf.all.secure_redirects + - net.ipv4.conf.default.secure_redirects + notify: + - flush routing cache + + - name: Enable Bad Error Message Protection (Scored) + sysctl: name=net.ipv4.icmp_ignore_bogus_error_responses value=1 ignoreerrors=yes sysctl_set=yes reload=yes state=present + notify: + - flush routing cache + + - name: Enable RFC-recommended Source Route Validation (Scored) + sysctl: name="{{item}}" value=1 ignoreerrors=yes sysctl_set=yes reload=yes state=present + with_items: + - net.ipv4.conf.all.rp_filter + - net.ipv4.conf.default.rp_filter + notify: + - flush routing cache + + - name: Enable packet forwarding for IPv4 + sysctl: name=net.ipv4.ip_forward value=1 + + - name: Do not send ICMP redirects (we are not a router) + sysctl: name=net.ipv4.conf.all.send_redirects value=0 + + + handlers: + - name: restart auditd + service: name=auditd state=restarted + + - name: restart rsyslog + service: name=rsyslog state=restarted + + - name: flush routing cache + shell: echo 1 > /proc/sys/net/ipv4/route/flush + + \ No newline at end of file diff --git a/templates/CIS.conf.j2 b/templates/CIS.conf.j2 new file mode 100644 index 0000000..96b3a59 --- /dev/null +++ b/templates/CIS.conf.j2 @@ -0,0 +1,15 @@ +*.emerg :omusrmsg:* +mail.* -/var/log/mail +mail.info -/var/log/mail.info +mail.warning -/var/log/mail.warn +mail.err /var/log/mail.err +news.crit -/var/log/news/news.crit +news.err -/var/log/news/news.err +news.notice -/var/log/news/news.notice +*.=warning;*.=err -/var/log/warn +*.crit /var/log/warn +*.*;mail.none;news.none -/var/log/messages +local0,local1.* -/var/log/localmessages +local2,local3.* -/var/log/localmessages +local4,local5.* -/var/log/localmessages +local6,local7.* -/var/log/localmessages \ No newline at end of file diff --git a/templates/audit.rules.j2 b/templates/audit.rules.j2 new file mode 100644 index 0000000..3464e2a --- /dev/null +++ b/templates/audit.rules.j2 @@ -0,0 +1,101 @@ +# This file contains the auditctl rules that are loaded +# whenever the audit daemon is started via the initscripts. +# The rules are simply the parameters that would be passed +# to auditctl. +# +# First rule - delete all +-D + +# Increase the buffers to survive stress events. +# Make this bigger for busy systems +-b 320 + +# Feel free to add below this line. See auditctl man page + +# Record Events That Modify Date and Time Information +{% if ansible_architecture == "x86_64" %} +-a always,exit -F arch=b64 -S clock_settime -k time-change +-a always,exit -F arch=b64 -S adjtimex -S settimeofday -k time-change +{% endif %} +-a always,exit -F arch=b32 -S clock_settime -k time-change +-a always,exit -F arch=b32 -S adjtimex -S settimeofday -S stime -k time-change +-w /etc/localtime -p wa -k time-change + +# Record Events That Modify User/Group Information +-w /etc/group -p wa -k identity +-w /etc/passwd -p wa -k identity +-w /etc/gshadow -p wa -k identity +-w /etc/shadow -p wa -k identity +-w /etc/security/opasswd -p wa -k identity + +# Record Events That Modify the System's Network Environment +{% if ansible_architecture == "x86_64" %} +-a exit,always -F arch=b64 -S sethostname -S setdomainname -k system-locale +{% endif %} +-a exit,always -F arch=b32 -S sethostname -S setdomainname -k system-locale +-w /etc/issue -p wa -k system-locale +-w /etc/issue.net -p wa -k system-locale +-w /etc/hosts -p wa -k system-locale +-w /etc/network/interfaces -p wa -k system-locale + +# Collect Login and Logout Events +-w /var/log/faillog -p wa -k logins +-w /var/log/lastlog -p wa -k logins +-w /var/log/tallylog -p wa -k logins + +# Collect Session Initiation Information +-w /var/run/utmp -p wa -k session +-w /var/log/wtmp -p wa -k session +-w /var/log/btmp -p wa -k session + +# Collect Discretionary Access Control Permission Modification Events +{% if ansible_architecture == "x86_64" %} +-a always,exit -F arch=b64 -S chmod -S fchmod -S fchmodat -F auid>=500 -F auid!=4294967295 -k perm_mod +-a always,exit -F arch=b64 -S chown -S fchown -S fchownat -S lchown -F auid>=500 -F auid!=4294967295 -k perm_mod +-a always,exit -F arch=b64 -S setxattr -S lsetxattr -S fsetxattr -S removexattr -S lremovexattr -S fremovexattr -F auid>=500 -F auid!=4294967295 -k perm_mod +{% endif %} +-a always,exit -F arch=b32 -S chmod -S fchmod -S fchmodat -F auid>=500 -F auid!=4294967295 -k perm_mod +-a always,exit -F arch=b32 -S chown -S fchown -S fchownat -S lchown -F auid>=500 -F auid!=4294967295 -k perm_mod +-a always,exit -F arch=b32 -S setxattr -S lsetxattr -S fsetxattr -S removexattr -S lremovexattr -S fremovexattr -F auid>=500 -F auid!=4294967295 -k perm_mod + +# Collect Unsuccessful Unauthorized Access Attempts to Files +{% if ansible_architecture == "x86_64" %} +-a always,exit -F arch=b64 -S creat -S open -S openat -S truncate -F exit=-EACCES -F auid>=500 -F auid!=4294967295 -k access +-a always,exit -F arch=b64 -S creat -S open -S openat -S truncate -F exit=-EPERM -F auid>=500 -F auid!=4294967295 -k access +{% endif %} +-a always,exit -F arch=b32 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EACCES -F auid>=500 -F auid!=4294967295 -k access +-a always,exit -F arch=b32 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EPERM -F auid>=500 -F auid!=4294967295 -k access + +# Collect Use of Privileged Commands +{% if privileged_programs is defined and privileged_programs.stdout_lines|length > 0 %} +{{ privileged_programs.stdout }} +{% endif %} + +# Collect Successful File System Mounts +{% if ansible_architecture == "x86_64" %} +-a always,exit -F arch=b64 -S mount -F auid>=500 -F auid!=4294967295 -k mounts +{% endif %} +-a always,exit -F arch=b32 -S mount -F auid>=500 -F auid!=4294967295 -k mounts + +# Collect File Deletion Events by User +{% if ansible_architecture == "x86_64" %} +-a always,exit -F arch=b64 -S unlink -S unlinkat -S rename -S renameat -F auid>=500 -F auid!=4294967295 -k delete +{% endif %} +-a always,exit -F arch=b32 -S unlink -S unlinkat -S rename -S renameat -F auid>=500 -F auid!=4294967295 -k delete + +# Collect Changes to System Administration Scope +-w /etc/sudoers -p wa -k scope + +# Collect System Administrator Actions (sudolog) +-w /var/log/sudo.log -p wa -k actions + +# Collect Kernel Module Loading and Unloading +{% if ansible_architecture == "x86_64" %} +-a always,exit -F arch=b64 -S init_module -S delete_module -k modules +{% endif %} +-a always,exit -F arch=b32 -S init_module -S delete_module -k modules +-w /sbin/insmod -p x -k modules +-w /sbin/rmmod -p x -k modules +-w /sbin/modprobe -p x -k modules + +-e 2 diff --git a/templates/auditd.conf.j2 b/templates/auditd.conf.j2 new file mode 100644 index 0000000..24aac73 --- /dev/null +++ b/templates/auditd.conf.j2 @@ -0,0 +1,32 @@ +# +# This file controls the configuration of the audit daemon +# + +log_file = /var/log/audit/audit.log +log_format = RAW +log_group = root +priority_boost = 4 +flush = INCREMENTAL +freq = 20 +num_logs = 5 +disp_qos = lossy +dispatcher = /sbin/audispd +name_format = NONE +##name = mydomain +max_log_file = 10 +max_log_file_action = keep_logs +space_left = 75 +space_left_action = email +action_mail_acct = {{ auditd_action_mail_acct }} +admin_space_left = 50 +admin_space_left_action = email +disk_full_action = SUSPEND +disk_error_action = SUSPEND +##tcp_listen_port = +tcp_listen_queue = 5 +tcp_max_per_addr = 1 +##tcp_client_ports = 1024-65535 +tcp_client_max_idle = 0 +enable_krb5 = no +krb5_principal = auditd +##krb5_key_file = /etc/audit/audit.key \ No newline at end of file diff --git a/templates/easy-rsa.vars.j2 b/templates/easy-rsa.vars.j2 new file mode 100644 index 0000000..19447c6 --- /dev/null +++ b/templates/easy-rsa.vars.j2 @@ -0,0 +1,198 @@ +# Easy-RSA 3 parameter settings + +# NOTE: If you installed Easy-RSA from your distro's package manager, don't edit +# this file in place -- instead, you should copy the entire easy-rsa directory +# to another location so future upgrades don't wipe out your changes. + +# HOW TO USE THIS FILE +# +# vars.example contains built-in examples to Easy-RSA settings. You MUST name +# this file 'vars' if you want it to be used as a configuration file. If you do +# not, it WILL NOT be automatically read when you call easyrsa commands. +# +# It is not necessary to use this config file unless you wish to change +# operational defaults. These defaults should be fine for many uses without the +# need to copy and edit the 'vars' file. +# +# All of the editable settings are shown commented and start with the command +# 'set_var' -- this means any set_var command that is uncommented has been +# modified by the user. If you're happy with a default, there is no need to +# define the value to its default. + +# NOTES FOR WINDOWS USERS +# +# Paths for Windows *MUST* use forward slashes, or optionally double-esscaped +# backslashes (single forward slashes are recommended.) This means your path to +# the openssl binary might look like this: +# "C:/Program Files/OpenSSL-Win32/bin/openssl.exe" + +# A little housekeeping: DON'T EDIT THIS SECTION +# +# Easy-RSA 3.x doesn't source into the environment directly. +# Complain if a user tries to do this: +if [ -z "$EASYRSA_CALLER" ]; then + echo "You appear to be sourcing an Easy-RSA 'vars' file." >&2 + echo "This is no longer necessary and is disallowed. See the section called" >&2 + echo "'How to use this file' near the top comments for more details." >&2 + return 1 +fi + +# DO YOUR EDITS BELOW THIS POINT + +# This variable should point to the top level of the easy-rsa tree. By default, +# this is taken to be the directory you are currently in. + +set_var EASYRSA "{{ easyrsa_dir }}/easyrsa3/" + +# If your OpenSSL command is not in the system PATH, you will need to define the +# path to it here. Normally this means a full path to the executable, otherwise +# you could have left it undefined here and the shown default would be used. +# +# Windows users, remember to use paths with forward-slashes (or escaped +# back-slashes.) Windows users should declare the full path to the openssl +# binary here if it is not in their system PATH. + +#set_var EASYRSA_OPENSSL "openssl" +# +# This sample is in Windows syntax -- edit it for your path if not using PATH: +#set_var EASYRSA_OPENSSL "C:/Program Files/OpenSSL-Win32/bin/openssl.exe" + +# Edit this variable to point to your soon-to-be-created key directory. +# +# WARNING: init-pki will do a rm -rf on this directory so make sure you define +# it correctly! (Interactive mode will prompt before acting.) + +set_var EASYRSA_PKI "$EASYRSA/pki" + +# Define X509 DN mode. +# This is used to adjust what elements are included in the Subject field as the DN +# (this is the "Distinguished Name.") +# Note that in cn_only mode the Organizational fields further below aren't used. +# +# Choices are: +# cn_only - use just a CN value +# org - use the "traditional" Country/Province/City/Org/OU/email/CN format + +set_var EASYRSA_DN "cn_only" + +# Organizational fields (used with 'org' mode and ignored in 'cn_only' mode.) +# These are the default values for fields which will be placed in the +# certificate. Don't leave any of these fields blank, although interactively +# you may omit any specific field by typing the "." symbol (not valid for +# email.) + +#set_var EASYRSA_REQ_COUNTRY "US" +#set_var EASYRSA_REQ_PROVINCE "California" +#set_var EASYRSA_REQ_CITY "San Francisco" +#set_var EASYRSA_REQ_ORG "Copyleft Certificate Co" +#set_var EASYRSA_REQ_EMAIL "me@example.net" +#set_var EASYRSA_REQ_OU "My Organizational Unit" + +# Choose a size in bits for your keypairs. The recommended value is 2048. Using +# 2048-bit keys is considered more than sufficient for many years into the +# future. Larger keysizes will slow down TLS negotiation and make key/DH param +# generation take much longer. Values up to 4096 should be accepted by most +# software. Only used when the crypto alg is rsa (see below.) + +# set_var EASYRSA_KEY_SIZE 2048 + +# The default crypto mode is rsa; ec can enable elliptic curve support. +# Note that not all software supports ECC, so use care when enabling it. +# Choices for crypto alg are: (each in lower-case) +# * rsa +# * ec + +set_var EASYRSA_ALGO ec + +# Define the named curve, used in ec mode only: + +set_var EASYRSA_CURVE prime256v1 + +# In how many days should the root CA key expire? + +set_var EASYRSA_CA_EXPIRE {{ easyrsa_ca_expire }} + +# In how many days should certificates expire? + +set_var EASYRSA_CERT_EXPIRE {{ easyrsa_cert_expire }} + +# How many days until the next CRL publish date? Note that the CRL can still be +# parsed after this timeframe passes. It is only used for an expected next +# publication date. + +#set_var EASYRSA_CRL_DAYS 180 + +# Support deprecated "Netscape" extensions? (choices "yes" or "no".) The default +# is "no" to discourage use of deprecated extensions. If you require this +# feature to use with --ns-cert-type, set this to "yes" here. This support +# should be replaced with the more modern --remote-cert-tls feature. If you do +# not use --ns-cert-type in your configs, it is safe (and recommended) to leave +# this defined to "no". When set to "yes", server-signed certs get the +# nsCertType=server attribute, and also get any NS_COMMENT defined below in the +# nsComment field. + +#set_var EASYRSA_NS_SUPPORT "no" + +# When NS_SUPPORT is set to "yes", this field is added as the nsComment field. +# Set this blank to omit it. With NS_SUPPORT set to "no" this field is ignored. + +#set_var EASYRSA_NS_COMMENT "Easy-RSA Generated Certificate" + +# A temp file used to stage cert extensions during signing. The default should +# be fine for most users; however, some users might want an alternative under a +# RAM-based FS, such as /dev/shm or /tmp on some systems. + +#set_var EASYRSA_TEMP_FILE "$EASYRSA_PKI/extensions.temp" + +# !! +# NOTE: ADVANCED OPTIONS BELOW THIS POINT +# PLAY WITH THEM AT YOUR OWN RISK +# !! + +# Broken shell command aliases: If you have a largely broken shell that is +# missing any of these POSIX-required commands used by Easy-RSA, you will need +# to define an alias to the proper path for the command. The symptom will be +# some form of a 'command not found' error from your shell. This means your +# shell is BROKEN, but you can hack around it here if you really need. These +# shown values are not defaults: it is up to you to know what you're doing if +# you touch these. +# +#alias awk="/alt/bin/awk" +#alias cat="/alt/bin/cat" + +# X509 extensions directory: +# If you want to customize the X509 extensions used, set the directory to look +# for extensions here. Each cert type you sign must have a matching filename, +# and an optional file named 'COMMON' is included first when present. Note that +# when undefined here, default behaviour is to look in $EASYRSA_PKI first, then +# fallback to $EASYRSA for the 'x509-types' dir. You may override this +# detection with an explicit dir here. +# +#set_var EASYRSA_EXT_DIR "$EASYRSA/x509-types" + +# OpenSSL config file: +# If you need to use a specific openssl config file, you can reference it here. +# Normally this file is auto-detected from a file named openssl-1.0.cnf from the +# EASYRSA_PKI or EASYRSA dir (in that order.) NOTE that this file is Easy-RSA +# specific and you cannot just use a standard config file, so this is an +# advanced feature. + +set_var EASYRSA_SSL_CONF "$EASYRSA/openssl-1.0.cnf" + +# Default CN: +# This is best left alone. Interactively you will set this manually, and BATCH +# callers are expected to set this themselves. + +set_var EASYRSA_REQ_CN "{{ server_name }}" + +# Cryptographic digest to use. +# Do not change this default unless you understand the security implications. +# Valid choices include: md5, sha1, sha256, sha224, sha384, sha512 + +#set_var EASYRSA_DIGEST "sha256" + +# Batch mode. Leave this disabled unless you intend to call Easy-RSA explicitly +# in batch mode without any user input, confirmation on dangerous operations, +# or most output. Setting this to any non-blank string enables batch mode. + +set_var EASYRSA_BATCH "{{ server_name }}" \ No newline at end of file diff --git a/templates/ipsec.conf.j2 b/templates/ipsec.conf.j2 new file mode 100644 index 0000000..6020256 --- /dev/null +++ b/templates/ipsec.conf.j2 @@ -0,0 +1,29 @@ +config setup + uniqueids = never # allow multiple connections per user + charondebug="ike 2, knl 2, cfg 2, net 2, esp 2, dmn 2, mgr 2" + +conn %default + dpdaction=clear + dpddelay=35s + dpdtimeout=300s + rekey=no + keyexchange=ikev2 + ike=aes128gcm16-sha2_256-prfsha256-ecp256! + esp=aes128gcm16-sha2_256-ecp256! + compress=yes + fragmentation=yes + + left=%any + leftauth=pubkey + leftid={{ server_name }} + leftcert={{ server_name }}.crt + leftsendcert=always + leftsubnet=0.0.0.0/0,::/0 + + right=%any + rightauth=pubkey + rightsourceip=10.0.0.0/24 + rightdns=8.8.8.8,8.8.4.4 + +conn ikev2-pubkey + auto=add \ No newline at end of file diff --git a/templates/ipsec.secrets.j2 b/templates/ipsec.secrets.j2 new file mode 100644 index 0000000..4cae96e --- /dev/null +++ b/templates/ipsec.secrets.j2 @@ -0,0 +1,2 @@ +: ECDSA {{ server_name }}.key + diff --git a/templates/mobileconfig.j2 b/templates/mobileconfig.j2 new file mode 100644 index 0000000..1fd2816 --- /dev/null +++ b/templates/mobileconfig.j2 @@ -0,0 +1,144 @@ + + + + + PayloadContent + + + IKEv2 + + AuthenticationMethod + Certificate + ChildSecurityAssociationParameters + + DiffieHellmanGroup + 19 + EncryptionAlgorithm + AES-128-GCM + IntegrityAlgorithm + SHA2-256 + LifeTimeInMinutes + 1440 + + DeadPeerDetectionRate + Medium + DisableMOBIKE + 0 + DisableRedirect + 0 + EnableCertificateRevocationCheck + 0 + EnablePFS + + IKESecurityAssociationParameters + + DiffieHellmanGroup + 19 + EncryptionAlgorithm + AES-128-GCM + IntegrityAlgorithm + SHA2-256 + LifeTimeInMinutes + 1440 + + LocalIdentifier + {{ item.0 }} + PayloadCertificateUUID + 1FB2907D-14D3-4BAB-A472-B304F4B7F7D9 + CertificateType + ECDSA256 + ServerCertificateIssuerCommonName + {{ server_name }} + RemoteAddress + {{ server_name }} + RemoteIdentifier + {{ server_name }} + UseConfigurationAttributeInternalIPSubnet + 0 + + IPv4 + + OverridePrimary + 1 + + PayloadDescription + Configures VPN settings + PayloadDisplayName + VPN + PayloadIdentifier + com.apple.vpn.managed.D247A30B-6023-4C8E-B3E3-FF1910A65E53 + PayloadType + com.apple.vpn.managed + PayloadUUID + D247A30B-6023-4C8E-B3E3-FF1910A65E53 + PayloadVersion + 1 + Proxies + + HTTPEnable + 0 + HTTPSEnable + 0 + + UserDefinedName + {{ server_name }} IKEv2 + VPNType + IKEv2 + + + Password + {{ easyrsa_p12_export_password }} + PayloadCertificateFileName + {{ item.0 }}.p12 + PayloadContent + + {{ item.1.stdout }} + + PayloadDescription + Adds a PKCS#12-formatted certificate + PayloadDisplayName + {{ item.0 }}.p12 + PayloadIdentifier + com.apple.security.pkcs12.1FB2907D-14D3-4BAB-A472-B304F4B7F7D9 + PayloadType + com.apple.security.pkcs12 + PayloadUUID + 1FB2907D-14D3-4BAB-A472-B304F4B7F7D9 + PayloadVersion + 1 + + + PayloadCertificateFileName + ca.crt + PayloadContent + + {{ PayloadContentCA.stdout }} + + PayloadDescription + Adds a CA root certificate + PayloadDisplayName + {{ server_name }} + PayloadIdentifier + com.apple.security.root.32EA3AAA-D19E-43EF-B357-608218745A38 + PayloadType + com.apple.security.root + PayloadUUID + 32EA3AAA-D19E-43EF-B357-608218745A38 + PayloadVersion + 1 + + + PayloadDisplayName + {{ server_name }} IKEv2 + PayloadIdentifier + donut.local.37CA79B1-FC6A-421F-960A-90F91FC983BE + PayloadRemovalDisallowed + + PayloadType + Configuration + PayloadUUID + 743B04A8-5725-45A2-B1BB-836F8C16DB0A + PayloadVersion + 1 + + diff --git a/templates/rsyslog.conf.j2 b/templates/rsyslog.conf.j2 new file mode 100644 index 0000000..2551380 --- /dev/null +++ b/templates/rsyslog.conf.j2 @@ -0,0 +1,61 @@ +# /etc/rsyslog.conf Configuration file for rsyslog. +# +# For more information see +# /usr/share/doc/rsyslog-doc/html/rsyslog_conf.html +# +# Default logging rules can be found in /etc/rsyslog.d/50-default.conf + +# +################# +#### MODULES #### +################# + +module(load="imuxsock") # provides support for local system logging +module(load="imklog") # provides kernel logging support +#module(load="immark") # provides --MARK-- message capability + +# provides UDP syslog reception +#module(load="imudp") +#input(type="imudp" port="514") + +# provides TCP syslog reception +#module(load="imtcp") +#input(type="imtcp" port="514") + +# Enable non-kernel facility klog messages +$KLogPermitNonKernelFacility on + +########################### +#### GLOBAL DIRECTIVES #### +########################### + +# +# Use traditional timestamp format. +# To enable high precision timestamps, comment out the following line. +# +$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat + +# Filter duplicated messages +$RepeatedMsgReduction on + +# +# Set the default permissions for all log files. +# +$FileOwner syslog +$FileGroup adm +$FileCreateMode 0640 +$DirCreateMode 0755 +$Umask 0022 +$PrivDropToUser syslog +$PrivDropToGroup syslog + +# +# Where to place spool and state files +# +$WorkDirectory /var/spool/rsyslog + +# +# Include all config files in /etc/rsyslog.d/ +# +$IncludeConfig /etc/rsyslog.d/*.conf + diff --git a/users.yml b/users.yml new file mode 100644 index 0000000..2b68ad9 --- /dev/null +++ b/users.yml @@ -0,0 +1,74 @@ +--- + +- name: Users management + hosts: users-management + gather_facts: false + remote_user: root + vars_files: + - config.cfg + + tasks: + - name: Build the client's pair + shell: > + ./easyrsa build-client-full {{ item }} nopass && + touch '{{ easyrsa_dir }}/easyrsa3/pki/{{ item }}_initialized' + args: + chdir: '{{ easyrsa_dir }}/easyrsa3/' + creates: '{{ easyrsa_dir }}/easyrsa3/pki/{{ item }}_initialized' + with_items: "{{ users }}" + + - name: Build the client's p12 + shell: > + openssl pkcs12 -in {{ easyrsa_dir }}/easyrsa3//pki/issued/{{ item }}.crt -inkey {{ easyrsa_dir }}/easyrsa3//pki/private/{{ item }}.key -export -name {{ item }} -out /{{ easyrsa_dir }}/easyrsa3//pki/private/{{ item }}.p12 -certfile {{ easyrsa_dir }}/easyrsa3//pki/ca.crt -passout pass:{{ easyrsa_p12_export_password }} && + touch '{{ easyrsa_dir }}/easyrsa3/pki/{{ item }}_p12_initialized' + args: + chdir: '{{ easyrsa_dir }}/easyrsa3/' + creates: '{{ easyrsa_dir }}/easyrsa3/pki/{{ item }}_p12_initialized' + with_items: "{{ users }}" + + - name: Get active users + shell: > + grep ^V pki/index.txt | grep -v "{{ server_name }}" | awk '{print $5}' | sed 's/\/CN=//g' + args: + chdir: '{{ easyrsa_dir }}/easyrsa3/' + register: valid_certs + + - name: Revoke non-existing users + shell: > + ipsec pki --signcrl --cacert {{ easyrsa_dir }}/easyrsa3//pki/ca.crt --cakey {{ easyrsa_dir }}/easyrsa3/pki/private/ca.key --reason superseded --cert {{ easyrsa_dir }}/easyrsa3//pki/issued/{{ item }}.crt > /etc/ipsec.d/crls/{{ item }}.der && + ./easyrsa revoke {{ item }} && + ipsec rereadcrls + args: + chdir: '{{ easyrsa_dir }}/easyrsa3/' + when: item not in users + with_items: "{{ valid_certs.stdout_lines }}" + + - name: Register p12 PayloadContent + shell: > + cat /{{ easyrsa_dir }}/easyrsa3//pki/private/{{ item }}.p12 | base64 + register: PayloadContent + with_items: "{{ users }}" + + - name: Register CA PayloadContent + shell: > + cat /{{ easyrsa_dir }}/easyrsa3/pki/ca.crt | base64 + register: PayloadContentCA + + - name: Build the mobileconfigs + template: src=mobileconfig.j2 dest=/{{ easyrsa_dir }}/easyrsa3//pki/private/{{ item.0 }}.mobileconfig mode=0600 + with_together: + - "{{ users }}" + - "{{ PayloadContent.results }}" + no_log: True + + - name: Fetch users P12 + fetch: src=/{{ easyrsa_dir }}/easyrsa3//pki/private/{{ item }}.p12 dest=configs/{{ server_name }}_{{ item }}.p12 flat=yes + with_items: "{{ users }}" + + - name: Fetch users mobileconfig + fetch: src=/{{ easyrsa_dir }}/easyrsa3//pki/private/{{ item }}.mobileconfig dest=configs/{{ server_name }}_{{ item }}.mobileconfig flat=yes + with_items: "{{ users }}" + + - name: Fetch server CA certificate + fetch: src=/{{ easyrsa_dir }}/easyrsa3/pki/ca.crt dest=configs/{{ server_name }}_ca.crt flat=yes + \ No newline at end of file diff --git a/vpn.yml b/vpn.yml new file mode 100644 index 0000000..6abd9f1 --- /dev/null +++ b/vpn.yml @@ -0,0 +1,150 @@ +--- + +- name: VPN Configuration + hosts: vpn-host + gather_facts: false + remote_user: root + vars_files: + - config.cfg + + tasks: + - name: Install StrongSwan + apt: name=strongswan state=latest update_cache=yes + + - name: Enforcing ipsec with apparmor + shell: aa-enforce "{{ item }}" + with_items: + - /usr/lib/ipsec/charon + - /usr/lib/ipsec/lookip + - /usr/lib/ipsec/stroke + notify: + - restart apparmor + + - name: Enable services + service: name={{ item }} enabled=yes + with_items: + - apparmor + - strongswan + + - name: Configure iptables so IPSec traffic can traverse the tunnel + iptables: table=nat chain=POSTROUTING source=10.0.0.0/24 jump=MASQUERADE + + - name: Setup the ipsec.conf file from our template + template: src=ipsec.conf.j2 dest=/etc/ipsec.conf owner=root group=root mode=644 + notify: + - restart strongswan + + - name: Setup the ipsec.secrets file + template: src=ipsec.secrets.j2 dest=/etc/ipsec.secrets owner=root group=root mode=600 + notify: + - restart strongswan + + - name: Fetch easy-rsa-ipsec repo + git: repo=git://github.com/ValdikSS/easy-rsa-ipsec.git dest="{{ easyrsa_dir }}" + + - name: Setup the vars file from our template + template: src=easy-rsa.vars.j2 dest={{ easyrsa_dir }}/easyrsa3/vars + + - name: Ensure the pki directory is not exist + file: dest={{ easyrsa_dir }}/easyrsa3/pki state=absent + when: easyrsa_reinit_existent == True + + - name: Build the pki enviroments + shell: > + ./easyrsa init-pki && + touch '{{ easyrsa_dir }}/easyrsa3/pki/pki_initialized' + args: + chdir: '{{ easyrsa_dir }}/easyrsa3/' + creates: '{{ easyrsa_dir }}/easyrsa3/pki/pki_initialized' + + - name: Build the CA pair + shell: > + ./easyrsa build-ca nopass && + touch {{ easyrsa_dir }}/easyrsa3/pki/ca_initialized + args: + chdir: '{{ easyrsa_dir }}/easyrsa3/' + creates: '{{ easyrsa_dir }}/easyrsa3/pki/ca_initialized' + notify: + - restart strongswan + + - name: Build the server pair # TODO: IP and DNS for certificate + shell: > + ./easyrsa build-server-full {{ server_name }} nopass && + touch '{{ easyrsa_dir }}/easyrsa3/pki/server_initialized' + args: + chdir: '{{ easyrsa_dir }}/easyrsa3/' + creates: '{{ easyrsa_dir }}/easyrsa3/pki/server_initialized' + notify: + - restart strongswan + + - name: Build the client's pair + shell: > + ./easyrsa build-client-full {{ item }} nopass && + touch '{{ easyrsa_dir }}/easyrsa3/pki/{{ item }}_initialized' + args: + chdir: '{{ easyrsa_dir }}/easyrsa3/' + creates: '{{ easyrsa_dir }}/easyrsa3/pki/{{ item }}_initialized' + with_items: "{{ users }}" + + - name: Build the client's p12 + shell: > + openssl pkcs12 -in {{ easyrsa_dir }}/easyrsa3//pki/issued/{{ item }}.crt -inkey {{ easyrsa_dir }}/easyrsa3//pki/private/{{ item }}.key -export -name {{ item }} -out /{{ easyrsa_dir }}/easyrsa3//pki/private/{{ item }}.p12 -certfile {{ easyrsa_dir }}/easyrsa3//pki/ca.crt -passout pass:{{ easyrsa_p12_export_password }} && + touch '{{ easyrsa_dir }}/easyrsa3/pki/{{ item }}_p12_initialized' + args: + chdir: '{{ easyrsa_dir }}/easyrsa3/' + creates: '{{ easyrsa_dir }}/easyrsa3/pki/{{ item }}_p12_initialized' + with_items: "{{ users }}" + + - name: Copy the CA cert to the strongswan directory + copy: remote_src=True src='{{ easyrsa_dir }}/easyrsa3/pki/ca.crt' dest=/etc/ipsec.d/cacerts/ca.crt owner=root group=root mode=0600 + notify: + - restart strongswan + + - name: Copy the server cert to the strongswan directory + copy: remote_src=True src='{{ easyrsa_dir }}/easyrsa3/pki/issued/{{ server_name }}.crt' dest=/etc/ipsec.d/certs/{{ server_name }}.crt owner=root group=root mode=0600 + notify: + - restart strongswan + + - name: Copy the server key to the strongswan directory + copy: remote_src=True src='{{ easyrsa_dir }}/easyrsa3/pki/private/{{ server_name }}.key' dest=/etc/ipsec.d/private/{{ server_name }}.key owner=root group=root mode=0600 + notify: + - restart strongswan + + - name: Register p12 PayloadContent + shell: > + cat /{{ easyrsa_dir }}/easyrsa3//pki/private/{{ item }}.p12 | base64 + register: PayloadContent + with_items: "{{ users }}" + + - name: Register CA PayloadContent + shell: > + cat /{{ easyrsa_dir }}/easyrsa3/pki/ca.crt | base64 + register: PayloadContentCA + + - name: Build the mobileconfigs + template: src=mobileconfig.j2 dest=/{{ easyrsa_dir }}/easyrsa3//pki/private/{{ item.0 }}.mobileconfig mode=0600 + with_together: + - "{{ users }}" + - "{{ PayloadContent.results }}" + no_log: True + + - name: Fetch users P12 + fetch: src=/{{ easyrsa_dir }}/easyrsa3//pki/private/{{ item }}.p12 dest=configs/{{ server_name }}_{{ item }}.p12 flat=yes + with_items: "{{ users }}" + + - name: Fetch users mobileconfig + fetch: src=/{{ easyrsa_dir }}/easyrsa3//pki/private/{{ item }}.mobileconfig dest=configs/{{ server_name }}_{{ item }}.mobileconfig flat=yes + with_items: "{{ users }}" + + - name: Fetch server CA certificate + fetch: src=/{{ easyrsa_dir }}/easyrsa3/pki/ca.crt dest=configs/{{ server_name }}_ca.crt flat=yes + + - name: Add server to the inventory file + local_action: lineinfile dest=inventory_users line="{{ inventory_hostname }}" insertafter='\[users-management\]\n' state=present + + handlers: + - name: restart strongswan + service: name=strongswan state=restarted + + - name: restart apparmor + service: name=apparmor state=restarted