Refactoring, Linting and additional tests (#1397)

* Refactoring, Linting and additional tests

* Vultr: Undefined variable and deprecation notes fix

* Travis-CI enable linters

* Azure: Update python requirements

* Update main.yml

* Update install.sh

* Add missing roles to ansible-lint

* Linting for skipped roles

* add .ansible-lint config
This commit is contained in:
Jack Ivanov 2019-04-26 17:48:28 +02:00 committed by Dan Guido
parent feb0091448
commit 25513cf925
61 changed files with 405 additions and 245 deletions

3
.ansible-lint Normal file
View file

@ -0,0 +1,3 @@
skip_list:
- '204'
verbosity: 1

View file

@ -8,15 +8,14 @@ services:
addons: addons:
apt: apt:
sources: sources: &default_sources
- sourceline: 'ppa:ubuntu-lxc/stable' - sourceline: 'ppa:ubuntu-lxc/stable'
- sourceline: 'ppa:wireguard/wireguard' - sourceline: 'ppa:wireguard/wireguard'
packages: packages: &default_packages
- python-pip - python-pip
- lxd - lxd
- expect-dev - expect-dev
- debootstrap - debootstrap
- shellcheck
- tree - tree
- bridge-utils - bridge-utils
- dnsutils - dnsutils
@ -25,7 +24,12 @@ addons:
- libffi-dev - libffi-dev
- python-dev - python-dev
- linux-headers-$(uname -r) - linux-headers-$(uname -r)
- wireguard-dkms - wireguard
- libxml2-utils
- crudini
- fping
- strongswan
- libstrongswan-standard-plugins
cache: cache:
directories: directories:
@ -37,39 +41,54 @@ before_cache:
- sudo tar cf $HOME/lxc/cache.tar /var/lib/lxd/images/ - sudo tar cf $HOME/lxc/cache.tar /var/lib/lxd/images/
- sudo chown $USER. $HOME/lxc/cache.tar - sudo chown $USER. $HOME/lxc/cache.tar
custom_scripts:
provisioning: &provisioning
- ssh-keygen -f ~/.ssh/id_rsa -t rsa -N ''
- sudo ./tests/pre-deploy.sh
- 'sed -i "s/^reduce_mtu:\s0$/reduce_mtu: 20/" config.cfg'
tests: &tests
- sudo ./tests/wireguard-client.sh
- sudo env "PATH=$PATH" ./tests/ipsec-client.sh
- sudo ./tests/ssh-tunnel.sh
matrix: matrix:
fast_finish: true fast_finish: true
include: include:
- stage: Test - stage: Tests
name: local deployment from docker name: code checks and linters
addons:
apt:
packages:
- shellcheck
script: script:
- docker build -t travis/algo .
- sudo tar xf $HOME/lxc/cache.tar -C / || echo "Didn't extract cache."
- sudo cp -f tests/lxd-bridge /etc/default/lxd-bridge
- ssh-keygen -f ~/.ssh/id_rsa -t rsa -N ''
- echo -e "#cloud-config\nssh_authorized_keys:\n - $(cat ~/.ssh/id_rsa.pub)" | sudo lxc profile set default user.user-data -
- sudo service lxd restart
- sudo lxc launch ubuntu:18.04 algo
- until host algo.lxd 10.0.8.1 -t A; do sleep 3; done
- export LXC_IP="$(dig algo.lxd @10.0.8.1 +short)"
- pip install -r requirements.txt
- pip install ansible-lint - pip install ansible-lint
- gem install awesome_bot - shellcheck algo install.sh
- ansible-playbook --version
- tree . -L 2
- ansible-playbook main.yml --syntax-check - ansible-playbook main.yml --syntax-check
- ansible-lint -v roles/*/*/*.yml playbooks/*.yml *.yml
- stage: Deploy
name: local deployment from docker
addons:
apt:
sources: *default_sources
packages: *default_packages
env: DEPLOY=docker
before_install: *provisioning
before_script:
- docker build -t travis/algo .
- ./tests/local-deploy.sh - ./tests/local-deploy.sh
- ./tests/update-users.sh - ./tests/update-users.sh
script: *tests
- stage: Test - stage: Deploy
name: cloud-init deployment name: cloud-init deployment
script: addons:
- sudo tar xf $HOME/lxc/cache.tar -C / || echo "Didn't extract cache." apt:
- sudo cp -f tests/lxd-bridge /etc/default/lxd-bridge sources: *default_sources
- sudo service lxd restart packages: *default_packages
- bash tests/cloud-init.sh | sudo lxc profile set default user.user-data - env: DEPLOY=cloud-init
- sudo lxc profile show default before_install: *provisioning
- sudo lxc launch ubuntu:18.04 algo before_script:
- until sudo lxc exec algo -- test -f /var/log/cloud-init-output.log; do echo 'Log file not found, Sleep for 3 seconds'; sleep 3; done - until sudo lxc exec algo -- test -f /var/log/cloud-init-output.log; do echo 'Log file not found, Sleep for 3 seconds'; sleep 3; done
- ( sudo lxc exec algo -- tail -f /var/log/cloud-init-output.log & ) - ( sudo lxc exec algo -- tail -f /var/log/cloud-init-output.log & )
- | - |
@ -78,11 +97,10 @@ matrix:
sleep 30; sleep 30;
done done
- sudo lxc exec algo -- test -f /opt/algo/configs/localhost/.config.yml - sudo lxc exec algo -- test -f /opt/algo/configs/localhost/.config.yml
- sudo lxc exec algo -- tar zcf /root/algo-configs.tar -C /opt/algo/configs/ .
# script: - sudo lxc file pull algo/root/algo-configs.tar ./
# - awesome_bot --allow-dupe --skip-save-results *.md docs/*.md --white-list paypal.com,do.co,microsoft.com,https://github.com/trailofbits/algo/archive/master.zip,https://github.com/trailofbits/algo/issues/new - sudo tar -C ./configs -zxf algo-configs.tar
# - shellcheck algo script: *tests
# - ansible-lint main.yml users.yml deploy_client.yml
notifications: notifications:
email: false email: false

9
algo
View file

@ -7,7 +7,8 @@ then
ACTIVATE_SCRIPT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/env/bin/activate" ACTIVATE_SCRIPT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/env/bin/activate"
if [ -f "$ACTIVATE_SCRIPT" ] if [ -f "$ACTIVATE_SCRIPT" ]
then then
source $ACTIVATE_SCRIPT # shellcheck source=/dev/null
source "$ACTIVATE_SCRIPT"
else else
echo "$ACTIVATE_SCRIPT not found. Did you follow documentation to install dependencies?" echo "$ACTIVATE_SCRIPT not found. Did you follow documentation to install dependencies?"
exit 1 exit 1
@ -15,8 +16,8 @@ then
fi fi
case "$1" in case "$1" in
update-users) PLAYBOOK=users.yml; ARGS="${@:2} -t update-users";; update-users) PLAYBOOK=users.yml; ARGS=( "${@:2}" -t update-users ) ;;
*) PLAYBOOK=main.yml; ARGS=${@} ;; *) PLAYBOOK=main.yml; ARGS=( "${@}" ) ;;
esac esac
ansible-playbook ${PLAYBOOK} ${ARGS} ansible-playbook ${PLAYBOOK} "${ARGS[@]}"

View file

@ -1,5 +1,7 @@
---
- name: Configure the client - name: Configure the client
hosts: localhost hosts: localhost
become: false
vars_files: vars_files:
- config.cfg - config.cfg
@ -8,9 +10,10 @@
add_host: add_host:
name: "{{ client_ip }}" name: "{{ client_ip }}"
groups: client-host groups: client-host
ansible_ssh_user: "{{ ssh_user }}" ansible_ssh_user: "{{ 'root' if client_ip == 'localhost' else ssh_user }}"
vpn_user: "{{ vpn_user }}" vpn_user: "{{ vpn_user }}"
server_ip: "{{ server_ip }}" IP_subject_alt_name: "{{ server_ip }}"
ansible_python_interpreter: "/usr/bin/python3"
- name: Configure the client and install required software - name: Configure the client and install required software
hosts: client-host hosts: client-host
@ -18,33 +21,6 @@
become: true become: true
vars_files: vars_files:
- config.cfg - config.cfg
- roles/vpn/defaults/main.yml - roles/strongswan/defaults/main.yml
pre_tasks:
- name: Get the OS
raw: uname -a
register: distribution
- name: Modify the server name fact
set_fact:
IP_subject_alt_name: "{{ server_ip }}"
- name: Ubuntu Xenial | Install prerequisites
raw: >
test -x /usr/bin/python2.7 ||
sudo apt-get update -qq && sudo apt-get install -qq -y python2.7 &&
sudo update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1
changed_when: false
when: "'ubuntu' in distribution.stdout|lower"
- name: Fedora 25 | Install prerequisites
raw: >
test -x /usr/bin/python2.7 ||
sudo dnf install python2 -y &&
sudo update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1 &&
rpm -ql python2-dnf || dnf install python2-dnf -y
changed_when: false
when: "'fedora' in distribution.stdout|lower"
roles: roles:
- { role: client, tags: ['client'] } - role: client

View file

@ -26,7 +26,8 @@
tasks: tasks:
- block: - block:
- pause: - name: Region prompt
pause:
prompt: | prompt: |
What provider would you like to use? What provider would you like to use?
{% for p in providers_map %} {% for p in providers_map %}
@ -41,7 +42,8 @@
set_fact: set_fact:
algo_provider: "{{ provider | default(providers_map[_algo_provider.user_input|default(omit)|int - 1]['alias']) }}" algo_provider: "{{ provider | default(providers_map[_algo_provider.user_input|default(omit)|int - 1]['alias']) }}"
- pause: - name: VPN server name prompt
pause:
prompt: | prompt: |
Name the vpn server Name the vpn server
[algo] [algo]
@ -50,21 +52,24 @@
- server_name is undefined - server_name is undefined
- algo_provider != "local" - algo_provider != "local"
- block: - block:
- pause: - name: Cellular On Demand prompt
pause:
prompt: | prompt: |
Do you want macOS/iOS IPsec clients to enable "Connect On Demand" when connected to cellular networks? Do you want macOS/iOS IPsec clients to enable "Connect On Demand" when connected to cellular networks?
[y/N] [y/N]
register: _ondemand_cellular register: _ondemand_cellular
when: ondemand_cellular is undefined when: ondemand_cellular is undefined
- pause: - name: Wi-Fi On Demand prompt
pause:
prompt: | prompt: |
Do you want macOS/iOS IPsec clients to enable "Connect On Demand" when connected to Wi-Fi? Do you want macOS/iOS IPsec clients to enable "Connect On Demand" when connected to Wi-Fi?
[y/N] [y/N]
register: _ondemand_wifi register: _ondemand_wifi
when: ondemand_wifi is undefined when: ondemand_wifi is undefined
- pause: - name: Trusted Wi-Fi networks prompt
pause:
prompt: | prompt: |
List the names of any trusted Wi-Fi networks where macOS/iOS IPsec clients should not use "Connect On Demand" List the names of any trusted Wi-Fi networks where macOS/iOS IPsec clients should not use "Connect On Demand"
(e.g., your home network. Comma-separated value, e.g., HomeNet,OfficeWifi,AlgoWiFi) (e.g., your home network. Comma-separated value, e.g., HomeNet,OfficeWifi,AlgoWiFi)
@ -74,14 +79,16 @@
- (ondemand_wifi|default(false)|bool) or - (ondemand_wifi|default(false)|bool) or
(booleans_map[_ondemand_wifi.user_input|default(omit)]|default(false)) (booleans_map[_ondemand_wifi.user_input|default(omit)]|default(false))
- pause: - name: Compatible ciphers prompt
pause:
prompt: | prompt: |
Do you want the VPN to support Windows 10 or Linux Desktop clients? (enables compatible ciphers and key exchange, less secure) Do you want the VPN to support Windows 10 or Linux Desktop clients? (enables compatible ciphers and key exchange, less secure)
[y/N] [y/N]
register: _windows register: _windows
when: windows is undefined when: windows is undefined
- pause: - name: Retain the CA key prompt
pause:
prompt: | prompt: |
Do you want to retain the CA key? (required to add users in the future, but less secure) Do you want to retain the CA key? (required to add users in the future, but less secure)
[y/N] [y/N]
@ -89,14 +96,16 @@
when: store_cakey is undefined when: store_cakey is undefined
when: ipsec_enabled when: ipsec_enabled
- pause: - name: DNS adblocking prompt
pause:
prompt: | prompt: |
Do you want to install an ad blocking DNS resolver on this VPN server? Do you want to install an ad blocking DNS resolver on this VPN server?
[y/N] [y/N]
register: _local_dns register: _local_dns
when: local_dns is undefined when: local_dns is undefined
- pause: - name: SSH tunneling prompt
pause:
prompt: | prompt: |
Do you want each user to have their own account for SSH tunneling? Do you want each user to have their own account for SSH tunneling?
[y/N] [y/N]
@ -107,36 +116,38 @@
set_fact: set_fact:
algo_server_name: >- algo_server_name: >-
{% if server_name is defined %}{% set _server = server_name %} {% if server_name is defined %}{% set _server = server_name %}
{%- elif _algo_server_name.user_input is defined and _algo_server_name.user_input != "" %}{% set _server = _algo_server_name.user_input %} {%- elif _algo_server_name.user_input is defined and _algo_server_name.user_input|length > 0 -%}
{%- set _server = _algo_server_name.user_input -%}
{%- else %}{% set _server = defaults['server_name'] %}{% endif -%} {%- else %}{% set _server = defaults['server_name'] %}{% endif -%}
{{ _server | regex_replace('(?!\.)(\W|_)', '-') }} {{ _server | regex_replace('(?!\.)(\W|_)', '-') }}
algo_ondemand_cellular: >- algo_ondemand_cellular: >-
{% if ondemand_cellular is defined %}{{ ondemand_cellular | bool }} {% if ondemand_cellular is defined %}{{ ondemand_cellular | bool }}
{%- elif _ondemand_cellular.user_input is defined and _ondemand_cellular.user_input != "" %}{{ booleans_map[_ondemand_cellular.user_input] | default(defaults['ondemand_cellular']) }} {%- elif _ondemand_cellular.user_input %}{{ booleans_map[_ondemand_cellular.user_input] | default(defaults['ondemand_cellular']) }}
{%- else %}false{% endif %} {%- else %}false{% endif %}
algo_ondemand_wifi: >- algo_ondemand_wifi: >-
{% if ondemand_wifi is defined %}{{ ondemand_wifi | bool }} {% if ondemand_wifi is defined %}{{ ondemand_wifi | bool }}
{%- elif _ondemand_wifi.user_input is defined and _ondemand_wifi.user_input != "" %}{{ booleans_map[_ondemand_wifi.user_input] | default(defaults['ondemand_wifi']) }} {%- elif _ondemand_wifi.user_input %}{{ booleans_map[_ondemand_wifi.user_input] | default(defaults['ondemand_wifi']) }}
{%- else %}false{% endif %} {%- else %}false{% endif %}
algo_ondemand_wifi_exclude: >- algo_ondemand_wifi_exclude: >-
{% if ondemand_wifi_exclude is defined %}{{ ondemand_wifi_exclude | b64encode }} {% if ondemand_wifi_exclude is defined %}{{ ondemand_wifi_exclude | b64encode }}
{%- elif _ondemand_wifi_exclude.user_input is defined and _ondemand_wifi_exclude.user_input != "" %}{{ _ondemand_wifi_exclude.user_input | b64encode }} {%- elif _ondemand_wifi_exclude.user_input is defined and _ondemand_wifi_exclude.user_input|length > 0 -%}
{{ _ondemand_wifi_exclude.user_input | b64encode }}
{%- else %}{{ '_null' | b64encode }}{% endif %} {%- else %}{{ '_null' | b64encode }}{% endif %}
algo_local_dns: >- algo_local_dns: >-
{% if local_dns is defined %}{{ local_dns | bool }} {% if local_dns is defined %}{{ local_dns | bool }}
{%- elif _local_dns.user_input is defined and _local_dns.user_input != "" %}{{ booleans_map[_local_dns.user_input] | default(defaults['local_dns']) }} {%- elif _local_dns.user_input %}{{ booleans_map[_local_dns.user_input] | default(defaults['local_dns']) }}
{%- else %}false{% endif %} {%- else %}false{% endif %}
algo_ssh_tunneling: >- algo_ssh_tunneling: >-
{% if ssh_tunneling is defined %}{{ ssh_tunneling | bool }} {% if ssh_tunneling is defined %}{{ ssh_tunneling | bool }}
{%- elif _ssh_tunneling.user_input is defined and _ssh_tunneling.user_input != "" %}{{ booleans_map[_ssh_tunneling.user_input] | default(defaults['ssh_tunneling']) }} {%- elif _ssh_tunneling.user_input %}{{ booleans_map[_ssh_tunneling.user_input] | default(defaults['ssh_tunneling']) }}
{%- else %}false{% endif %} {%- else %}false{% endif %}
algo_windows: >- algo_windows: >-
{% if windows is defined %}{{ windows | bool }} {% if windows is defined %}{{ windows | bool }}
{%- elif _windows.user_input is defined and _windows.user_input != "" %}{{ booleans_map[_windows.user_input] | default(defaults['windows']) }} {%- elif _windows.user_input %}{{ booleans_map[_windows.user_input] | default(defaults['windows']) }}
{%- else %}false{% endif %} {%- else %}false{% endif %}
algo_store_cakey: >- algo_store_cakey: >-
{% if store_cakey is defined %}{{ store_cakey | bool }} {% if store_cakey is defined %}{{ store_cakey | bool }}
{%- elif _store_cakey.user_input is defined and _store_cakey.user_input != "" %}{{ booleans_map[_store_cakey.user_input] | default(defaults['store_cakey']) }} {%- elif _store_cakey.user_input %}{{ booleans_map[_store_cakey.user_input] | default(defaults['store_cakey']) }}
{%- else %}false{% endif %} {%- else %}false{% endif %}
rescue: rescue:
- include_tasks: playbooks/rescue.yml - include_tasks: playbooks/rescue.yml

View file

@ -36,12 +36,11 @@ installRequirements() {
} }
getAlgo() { getAlgo() {
[ ! -d "algo" ] && git clone https://github.com/${REPO_SLUG} algo [ ! -d "algo" ] && git clone "https://github.com/${REPO_SLUG}" -b "${REPO_BRANCH}" algo
cd algo cd algo
git checkout ${REPO_BRANCH} python -m virtualenv --python="$(command -v python2)" .venv
# shellcheck source=/dev/null
python -m virtualenv --python=`which python2` .venv
. .venv/bin/activate . .venv/bin/activate
python -m pip install -U pip virtualenv python -m pip install -U pip virtualenv
python -m pip install -r requirements.txt python -m pip install -r requirements.txt
@ -50,27 +49,23 @@ getAlgo() {
publicIpFromInterface() { publicIpFromInterface() {
echo "Couldn't find a valid ipv4 address, using the first IP found on the interfaces as the endpoint." echo "Couldn't find a valid ipv4 address, using the first IP found on the interfaces as the endpoint."
DEFAULT_INTERFACE="$(ip -4 route list match default | grep -Eo "dev .*" | awk '{print $2}')" DEFAULT_INTERFACE="$(ip -4 route list match default | grep -Eo "dev .*" | awk '{print $2}')"
ENDPOINT=$(ip -4 addr sh dev $DEFAULT_INTERFACE | grep -w inet | head -n1 | awk '{print $2}' | grep -oE '\b([0-9]{1,3}\.){3}[0-9]{1,3}\b') ENDPOINT=$(ip -4 addr sh dev "$DEFAULT_INTERFACE" | grep -w inet | head -n1 | awk '{print $2}' | grep -oE '\b([0-9]{1,3}\.){3}[0-9]{1,3}\b')
export ENDPOINT=$ENDPOINT export ENDPOINT=$ENDPOINT
echo "Using ${ENDPOINT} as the endpoint" echo "Using ${ENDPOINT} as the endpoint"
} }
publicIpFromMetadata() { publicIpFromMetadata() {
if curl -s http://169.254.169.254/metadata/v1/vendor-data | grep DigitalOcean >/dev/null; then if curl -s http://169.254.169.254/metadata/v1/vendor-data | grep DigitalOcean >/dev/null; then
PROVIDER="digitalocean"
ENDPOINT="$(curl -s http://169.254.169.254/metadata/v1/interfaces/public/0/ipv4/address)" ENDPOINT="$(curl -s http://169.254.169.254/metadata/v1/interfaces/public/0/ipv4/address)"
elif test "$(curl -s http://169.254.169.254/latest/meta-data/services/domain)" = "amazonaws.com"; then elif test "$(curl -s http://169.254.169.254/latest/meta-data/services/domain)" = "amazonaws.com"; then
PROVIDER="amazon"
ENDPOINT="$(curl -s http://169.254.169.254/latest/meta-data/public-ipv4)" ENDPOINT="$(curl -s http://169.254.169.254/latest/meta-data/public-ipv4)"
elif host -t A -W 10 metadata.google.internal 127.0.0.53 >/dev/null; then elif host -t A -W 10 metadata.google.internal 127.0.0.53 >/dev/null; then
PROVIDER="gce"
ENDPOINT="$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip")" ENDPOINT="$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip")"
elif test "$(curl -s -H Metadata:true 'http://169.254.169.254/metadata/instance/compute/publisher/?api-version=2017-04-02&format=text')" = "Canonical"; then elif test "$(curl -s -H Metadata:true 'http://169.254.169.254/metadata/instance/compute/publisher/?api-version=2017-04-02&format=text')" = "Canonical"; then
PROVIDER="azure"
ENDPOINT="$(curl -H Metadata:true 'http://169.254.169.254/metadata/instance/network/interface/0/ipv4/ipAddress/0/publicIpAddress?api-version=2017-04-02&format=text')" ENDPOINT="$(curl -H Metadata:true 'http://169.254.169.254/metadata/instance/network/interface/0/ipv4/ipAddress/0/publicIpAddress?api-version=2017-04-02&format=text')"
fi fi
if echo ${ENDPOINT} | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b"; then if echo "${ENDPOINT}" | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b"; then
export ENDPOINT=$ENDPOINT export ENDPOINT=$ENDPOINT
echo "Using ${ENDPOINT} as the endpoint" echo "Using ${ENDPOINT} as the endpoint"
else else
@ -82,23 +77,25 @@ deployAlgo() {
getAlgo getAlgo
cd /opt/algo cd /opt/algo
# shellcheck source=/dev/null
. .venv/bin/activate . .venv/bin/activate
export HOME=/root export HOME=/root
export ANSIBLE_LOCAL_TEMP=/root/.ansible/tmp export ANSIBLE_LOCAL_TEMP=/root/.ansible/tmp
export ANSIBLE_REMOTE_TEMP=/root/.ansible/tmp export ANSIBLE_REMOTE_TEMP=/root/.ansible/tmp
# shellcheck disable=SC2086
ansible-playbook main.yml \ ansible-playbook main.yml \
-e provider=local \ -e provider=local \
-e ondemand_cellular=${ONDEMAND_CELLULAR} \ -e "ondemand_cellular=${ONDEMAND_CELLULAR}" \
-e ondemand_wifi=${ONDEMAND_WIFI} \ -e "ondemand_wifi=${ONDEMAND_WIFI}" \
-e ondemand_wifi_exclude=${ONDEMAND_WIFI_EXCLUDE} \ -e "ondemand_wifi_exclude=${ONDEMAND_WIFI_EXCLUDE}" \
-e windows=${WINDOWS} \ -e "windows=${WINDOWS}" \
-e store_cakey=${STORE_CAKEY} \ -e "store_cakey=${STORE_CAKEY}" \
-e local_dns=${LOCAL_DNS} \ -e "local_dns=${LOCAL_DNS}" \
-e ssh_tunneling=${SSH_TUNNELING} \ -e "ssh_tunneling=${SSH_TUNNELING}" \
-e endpoint=$ENDPOINT \ -e "endpoint=$ENDPOINT" \
-e users=$(echo "$USERS" | jq -Rc 'split(",")') \ -e "users=$(echo "$USERS" | jq -Rc 'split(",")')" \
-e server=localhost \ -e server=localhost \
-e ssh_user=root \ -e ssh_user=root \
-e "${EXTRA_VARS}" \ -e "${EXTRA_VARS}" \
@ -106,7 +103,7 @@ deployAlgo() {
tee /var/log/algo.log tee /var/log/algo.log
} }
if test $METHOD = "cloud"; then if test "$METHOD" = "cloud"; then
publicIpFromMetadata publicIpFromMetadata
fi fi

View file

@ -1,4 +1,15 @@
--- ---
- hosts: localhost
become: false
tasks:
- name: Verify Ansible meets Drupal VM's version requirements.
assert:
that: "ansible_version.full is version('2.7.10', '==')"
msg: >
Ansible version is {{ ansible_version.full }}.
You must update the requirements to use this version of Algo.
Try to run python -m pip install -U -r requirements.txt
- name: Include prompts playbook - name: Include prompts playbook
import_playbook: input.yml import_playbook: input.yml

View file

@ -1,7 +1,7 @@
--- ---
- block:
- name: Display the invocation environment - name: Display the invocation environment
local_action: shell: >
module: shell
./algo-showenv.sh \ ./algo-showenv.sh \
'algo_provider "{{ algo_provider }}"' \ 'algo_provider "{{ algo_provider }}"' \
'algo_ondemand_cellular "{{ algo_ondemand_cellular }}"' \ 'algo_ondemand_cellular "{{ algo_ondemand_cellular }}"' \
@ -16,14 +16,17 @@
tags: debug tags: debug
- name: Install the requirements - name: Install the requirements
local_action: pip:
module: pip
state: latest state: latest
name: name:
- pyOpenSSL - pyOpenSSL
- jinja2==2.8 - jinja2==2.8
- segno - segno
tags: always tags:
- always
- skip_ansible_lint
delegate_to: localhost
become: false
- name: Generate the SSH private key - name: Generate the SSH private key
openssl_privatekey: openssl_privatekey:

View file

@ -2,4 +2,5 @@
- debug: - debug:
var: fail_hint var: fail_hint
- fail: - name: Fail the installation
fail:

View file

@ -1 +1 @@
ansible==2.5.2 ansible==2.7.10

View file

@ -1,4 +1,3 @@
--- ---
- name: restart strongswan - name: restart strongswan
service: name=strongswan state=restarted service: name=strongswan state=restarted

View file

@ -8,13 +8,21 @@
package: name="{{ item }}" state=present package: name="{{ item }}" state=present
with_items: with_items:
- "{{ prerequisites }}" - "{{ prerequisites }}"
register: result
until: result is succeeded
retries: 10
delay: 3
- name: Install strongSwan - name: Install strongSwan
package: name=strongswan state=present package: name=strongswan state=present
register: result
until: result is succeeded
retries: 10
delay: 3
- name: Setup the ipsec config - name: Setup the ipsec config
template: template:
src: "roles/vpn/templates/client_ipsec.conf.j2" src: "roles/strongswan/templates/client_ipsec.conf.j2"
dest: "{{ configs_prefix }}/ipsec.{{ IP_subject_alt_name }}.conf" dest: "{{ configs_prefix }}/ipsec.{{ IP_subject_alt_name }}.conf"
mode: '0644' mode: '0644'
with_items: with_items:
@ -24,7 +32,7 @@
- name: Setup the ipsec secrets - name: Setup the ipsec secrets
template: template:
src: "roles/vpn/templates/client_ipsec.secrets.j2" src: "roles/strongswan/templates/client_ipsec.secrets.j2"
dest: "{{ configs_prefix }}/ipsec.{{ IP_subject_alt_name }}.secrets" dest: "{{ configs_prefix }}/ipsec.{{ IP_subject_alt_name }}.secrets"
mode: '0600' mode: '0600'
with_items: with_items:

View file

@ -1,6 +1,6 @@
--- ---
- name: Set OS specific facts
- set_fact: set_fact:
prerequisites: prerequisites:
- epel-release - epel-release
configs_prefix: /etc/strongswan configs_prefix: /etc/strongswan

View file

@ -1,5 +1,6 @@
--- ---
- name: Set OS specific facts
- set_fact: set_fact:
prerequisites: [] prerequisites:
- libstrongswan-standard-plugins
configs_prefix: /etc configs_prefix: /etc

View file

@ -1,6 +1,6 @@
--- ---
- name: Set OS specific facts
- set_fact: set_fact:
prerequisites: prerequisites:
- libselinux-python - libselinux-python
configs_prefix: /etc/strongswan configs_prefix: /etc/strongswan

View file

@ -1,5 +1,6 @@
--- ---
- name: Set OS specific facts
- set_fact: set_fact:
prerequisites: [] prerequisites:
- libstrongswan-standard-plugins
configs_prefix: /etc configs_prefix: /etc

View file

@ -9,14 +9,14 @@
- set_fact: - set_fact:
algo_region: >- algo_region: >-
{% if region is defined %}{{ region }} {% if region is defined %}{{ region }}
{%- elif _algo_region.user_input is defined and _algo_region.user_input != "" %}{{ azure_regions[_algo_region.user_input | int -1 ]['name'] }} {%- elif _algo_region.user_input %}{{ azure_regions[_algo_region.user_input | int -1 ]['name'] }}
{%- else %}{{ azure_regions[default_region | int - 1]['name'] }}{% endif %} {%- else %}{{ azure_regions[default_region | int - 1]['name'] }}{% endif %}
- name: Create AlgoVPN Server - name: Create AlgoVPN Server
azure_rm_deployment: azure_rm_deployment:
state: present state: present
deployment_name: "{{ algo_server_name }}" deployment_name: "{{ algo_server_name }}"
template: "{{ lookup('file', 'deployment.json') }}" template: "{{ lookup('file', role_path + '/files/deployment.json') }}"
secret: "{{ secret }}" secret: "{{ secret }}"
tenant: "{{ tenant }}" tenant: "{{ tenant }}"
client_id: "{{ client_id }}" client_id: "{{ client_id }}"

View file

@ -10,23 +10,32 @@
name: name:
- packaging - packaging
- requests[security] - requests[security]
- azure-mgmt-compute>=2.0.0,<3 - azure-cli-core==2.0.35
- azure-mgmt-network>=1.3.0,<2 - azure-cli-nspkg==3.0.2
- azure-mgmt-storage>=1.5.0,<2 - azure-common==1.1.11
- azure-mgmt-resource>=1.1.0,<2 - azure-mgmt-batch==4.1.0
- azure-storage>=0.35.1,<0.36 - azure-mgmt-compute==2.1.0
- azure-cli-core>=2.0.12,<3 - azure-mgmt-containerinstance==0.4.0
- azure-mgmt-containerregistry==2.0.0
- azure-mgmt-containerservice==3.0.1
- azure-mgmt-dns==1.2.0
- azure-mgmt-keyvault==0.40.0
- azure-mgmt-marketplaceordering==0.1.0
- azure-mgmt-monitor==0.5.2
- azure-mgmt-network==1.7.1
- azure-mgmt-nspkg==2.0.0
- azure-mgmt-rdbms==1.2.0
- azure-mgmt-resource==1.2.2
- azure-mgmt-sql==0.7.1
- azure-mgmt-storage==1.5.0
- azure-mgmt-trafficmanager==0.50.0
- azure-mgmt-web==0.32.0
- azure-nspkg==2.0.0
- azure-storage==0.35.1
- msrest==0.4.29 - msrest==0.4.29
- msrestazure==0.4.31 - msrestazure==0.4.31
- azure-mgmt-dns>=1.0.1,<2 - azure-keyvault==1.0.0a1
- azure-mgmt-keyvault>=0.40.0,<0.41 - azure-graphrbac==0.40.0
- azure-mgmt-batch>=4.1.0,<5
- azure-mgmt-sql>=0.7.1,<0.8
- azure-mgmt-web>=0.32.0,<0.33
- azure-mgmt-containerservice>=2.0.0,<3.0.0
- azure-mgmt-containerregistry>=1.0.1
- azure-mgmt-rdbms==1.2.0
- azure-mgmt-containerinstance==0.4.0
state: latest state: latest
virtualenv: "{{ azure_venv }}" virtualenv: "{{ azure_venv }}"
virtualenv_python: python2.7 virtualenv_python: python2.7

View file

@ -10,7 +10,7 @@
set_fact: set_fact:
algo_do_region: >- algo_do_region: >-
{% if region is defined %}{{ region }} {% if region is defined %}{{ region }}
{%- elif _algo_region.user_input is defined and _algo_region.user_input != "" %}{{ do_regions[_algo_region.user_input | int -1 ]['slug'] }} {%- elif _algo_region.user_input %}{{ do_regions[_algo_region.user_input | int -1 ]['slug'] }}
{%- else %}{{ do_regions[default_region | int - 1]['slug'] }}{% endif %} {%- else %}{{ do_regions[default_region | int - 1]['slug'] }}{% endif %}
public_key: "{{ lookup('file', '{{ SSH_keys.public }}') }}" public_key: "{{ lookup('file', '{{ SSH_keys.public }}') }}"
@ -22,7 +22,7 @@
api_token: "{{ algo_do_token }}" api_token: "{{ algo_do_token }}"
name: "{{ SSH_keys.comment }}" name: "{{ SSH_keys.comment }}"
register: ssh_keys register: ssh_keys
until: ssh_keys.changed != true until: not ssh_keys.changed
retries: 10 retries: 10
delay: 1 delay: 1
@ -83,7 +83,7 @@
api_token: "{{ algo_do_token }}" api_token: "{{ algo_do_token }}"
name: "{{ SSH_keys.comment }}" name: "{{ SSH_keys.comment }}"
register: ssh_keys register: ssh_keys
until: ssh_keys.changed != true until: not ssh_keys.changed
retries: 10 retries: 10
delay: 1 delay: 1

View file

@ -6,7 +6,7 @@
stack_name: "{{ stack_name }}" stack_name: "{{ stack_name }}"
state: "present" state: "present"
region: "{{ algo_region }}" region: "{{ algo_region }}"
template: roles/cloud-ec2/files/stack.yml template: roles/cloud-ec2/files/stack.yaml
template_parameters: template_parameters:
InstanceTypeParameter: "{{ cloud_providers.ec2.size }}" InstanceTypeParameter: "{{ cloud_providers.ec2.size }}"
PublicSSHKeyParameter: "{{ lookup('file', SSH_keys.public) }}" PublicSSHKeyParameter: "{{ lookup('file', SSH_keys.public) }}"

View file

@ -9,7 +9,7 @@
- set_fact: - set_fact:
algo_region: >- algo_region: >-
{% if region is defined %}{{ region }} {% if region is defined %}{{ region }}
{%- elif _algo_region.user_input is defined and _algo_region.user_input != "" %}{{ aws_regions[_algo_region.user_input | int -1 ]['region_name'] }} {%- elif _algo_region.user_input %}{{ aws_regions[_algo_region.user_input | int -1 ]['region_name'] }}
{%- else %}{{ aws_regions[default_region | int - 1]['region_name'] }}{% endif %} {%- else %}{{ aws_regions[default_region | int - 1]['region_name'] }}{% endif %}
stack_name: "{{ algo_server_name | replace('.', '-') }}" stack_name: "{{ algo_server_name | replace('.', '-') }}"

View file

@ -63,5 +63,5 @@
- set_fact: - set_fact:
algo_region: >- algo_region: >-
{% if region is defined %}{{ region }} {% if region is defined %}{{ region }}
{%- elif _gce_region.user_input is defined and _gce_region.user_input != "" %}{{ gce_regions[_gce_region.user_input | int -1 ] }} {%- elif _gce_region.user_input %}{{ gce_regions[_gce_region.user_input | int -1 ] }}
{%- else %}{{ gce_regions[default_region | int - 1] }}{% endif %} {%- else %}{{ gce_regions[default_region | int - 1] }}{% endif %}

View file

@ -57,5 +57,5 @@
- set_fact: - set_fact:
algo_region: >- algo_region: >-
{% if region is defined %}{{ region }} {% if region is defined %}{{ region }}
{%- elif _algo_region.user_input is defined and _algo_region.user_input != "" %}{{ lightsail_regions[_algo_region.user_input | int -1 ]['name'] }} {%- elif _algo_region.user_input %}{{ lightsail_regions[_algo_region.user_input | int -1 ]['name'] }}
{%- else %}{{ lightsail_regions[default_region | int - 1]['name'] }}{% endif %} {%- else %}{{ lightsail_regions[default_region | int - 1]['name'] }}{% endif %}

View file

@ -1,7 +1,7 @@
--- ---
- fail: - fail:
msg: "OpenStack credentials are not set. Download it from the OpenStack dashboard->Compute->API Access and source it in the shell (eg: source /tmp/dhc-openrc.sh)" msg: "OpenStack credentials are not set. Download it from the OpenStack dashboard->Compute->API Access and source it in the shell (eg: source /tmp/dhc-openrc.sh)"
when: lookup('env', 'OS_AUTH_URL') == "" when: lookup('env', 'OS_AUTH_URL')|length <= 0
- name: Build python virtual environment - name: Build python virtual environment
import_tasks: venv.yml import_tasks: venv.yml

View file

@ -30,5 +30,5 @@
algo_scaleway_org: "{{ scaleway_org | default(_scaleway_org.user_input|default(omit)) }}" algo_scaleway_org: "{{ scaleway_org | default(_scaleway_org.user_input|default(omit)) }}"
algo_region: >- algo_region: >-
{% if region is defined %}{{ region }} {% if region is defined %}{{ region }}
{%- elif _algo_region.user_input is defined and _algo_region.user_input != "" %}{{ scaleway_regions[_algo_region.user_input | int -1 ]['alias'] }} {%- elif _algo_region.user_input %}{{ scaleway_regions[_algo_region.user_input | int -1 ]['alias'] }}
{%- else %}{{ scaleway_regions.0.alias }}{% endif %} {%- else %}{{ scaleway_regions.0.alias }}{% endif %}

View file

@ -1,16 +1,16 @@
--- ---
- block:
- name: Include prompts - name: Include prompts
import_tasks: prompts.yml import_tasks: prompts.yml
- block:
- name: Upload the SSH key - name: Upload the SSH key
vr_ssh_key: vultr_ssh_key:
name: "{{ SSH_keys.comment }}" name: "{{ SSH_keys.comment }}"
ssh_key: "{{ lookup('file', '{{ SSH_keys.public }}') }}" ssh_key: "{{ lookup('file', '{{ SSH_keys.public }}') }}"
register: ssh_key register: ssh_key
- name: Creating a server - name: Creating a server
vr_server: vultr_server:
name: "{{ algo_server_name }}" name: "{{ algo_server_name }}"
hostname: "{{ algo_server_name }}" hostname: "{{ algo_server_name }}"
os: "{{ cloud_providers.vultr.os }}" os: "{{ cloud_providers.vultr.os }}"

View file

@ -54,5 +54,5 @@
set_fact: set_fact:
algo_vultr_region: >- algo_vultr_region: >-
{% if region is defined %}{{ region }} {% if region is defined %}{{ region }}
{%- elif _algo_region.user_input is defined and _algo_region.user_input != "" %}{{ vultr_regions[_algo_region.user_input | int -1 ]['name'] }} {%- elif _algo_region.user_input %}{{ vultr_regions[_algo_region.user_input | int -1 ]['name'] }}
{%- else %}{{ vultr_regions[default_region | int - 1]['name'] }}{% endif %} {%- else %}{{ vultr_regions[default_region | int - 1]['name'] }}{% endif %}

View file

@ -20,8 +20,5 @@
ifconfig lo100 inet {{ local_service_ip }} netmask 255.255.255.255 && ifconfig lo100 inet {{ local_service_ip }} netmask 255.255.255.255 &&
ifconfig lo100 inet6 FCAA::1/64; echo $? ifconfig lo100 inet6 FCAA::1/64; echo $?
- name: save iptables
shell: service netfilter-persistent save
- name: restart iptables - name: restart iptables
service: name=netfilter-persistent state=restarted service: name=netfilter-persistent state=restarted

View file

@ -1,26 +1,26 @@
--- ---
- block: - block:
- name: Generate password for the CA key - name: Generate password for the CA key
local_action: command: openssl rand -hex 16
module: shell
openssl rand -hex 16
register: CA_password register: CA_password
- name: Generate p12 export password - name: Generate p12 export password
local_action: shell: >
module: shell openssl rand 8 |
openssl rand 8 | python -c 'import sys,string; chars=string.ascii_letters + string.digits + "_@"; print("".join([chars[ord(c) % 64] for c in list(sys.stdin.read())]))' python -c 'import sys,string; chars=string.ascii_letters + string.digits + "_@"; print("".join([chars[ord(c) % 64] for c in list(sys.stdin.read())]))'
register: p12_password_generated register: p12_password_generated
when: p12_password is not defined when: p12_password is not defined
tags: update-users tags: update-users
become: false become: false
delegate_to: localhost
- name: Define facts - name: Define facts
set_fact: set_fact:
p12_export_password: "{{ p12_password|default(p12_password_generated.stdout) }}" p12_export_password: "{{ p12_password|default(p12_password_generated.stdout) }}"
tags: update-users tags: update-users
- set_fact: - name: Set facts
set_fact:
CA_password: "{{ CA_password.stdout }}" CA_password: "{{ CA_password.stdout }}"
IP_subject_alt_name: "{{ IP_subject_alt_name }}" IP_subject_alt_name: "{{ IP_subject_alt_name }}"
@ -31,5 +31,5 @@
- name: Check size of MTU - name: Check size of MTU
set_fact: set_fact:
reduce_mtu: "{% if reduce_mtu|int == 0 and ansible_default_ipv4['mtu']|int < 1500 %}{{ 1500 - ansible_default_ipv4['mtu']|int }}{% else %}{{ reduce_mtu|int }}{% endif %}" reduce_mtu: "{{ 1500 - ansible_default_ipv4['mtu']|int if reduce_mtu|int == 0 and ansible_default_ipv4['mtu']|int < 1500 else reduce_mtu|int }}"
tags: always tags: always

View file

@ -17,7 +17,8 @@
- name: Gather additional facts - name: Gather additional facts
import_tasks: facts.yml import_tasks: facts.yml
- set_fact: - name: Set OS specific facts
set_fact:
config_prefix: "/usr/local/" config_prefix: "/usr/local/"
strongswan_shell: /usr/sbin/nologin strongswan_shell: /usr/sbin/nologin
strongswan_home: /var/empty strongswan_home: /var/empty
@ -73,5 +74,6 @@
shell: > shell: >
kldstat -n ipfw.ko || kldload ipfw ; sysctl net.inet.ip.fw.enable=0 && kldstat -n ipfw.ko || kldload ipfw ; sysctl net.inet.ip.fw.enable=0 &&
bash /etc/rc.firewall && sysctl net.inet.ip.fw.enable=1 bash /etc/rc.firewall && sysctl net.inet.ip.fw.enable=1
changed_when: false
- meta: flush_handlers - meta: flush_handlers

View file

@ -2,6 +2,7 @@
- name: Check the system - name: Check the system
raw: uname -a raw: uname -a
register: OS register: OS
changed_when: false
tags: tags:
- update-users - update-users
@ -17,7 +18,7 @@
- name: Sysctl tuning - name: Sysctl tuning
sysctl: name="{{ item.item }}" value="{{ item.value }}" sysctl: name="{{ item.item }}" value="{{ item.value }}"
when: item.item != "" when: item.item
with_items: with_items:
- "{{ sysctl|default([]) }}" - "{{ sysctl|default([]) }}"
tags: tags:

View file

@ -25,8 +25,7 @@
ignore_errors: true ignore_errors: true
- name: Wait until SSH becomes ready... - name: Wait until SSH becomes ready...
local_action: wait_for:
module: wait_for
port: 22 port: 22
host: "{{ inventory_hostname }}" host: "{{ inventory_hostname }}"
search_regex: OpenSSH search_regex: OpenSSH
@ -34,6 +33,7 @@
timeout: 320 timeout: 320
when: reboot_required is defined and reboot_required.stdout == 'required' when: reboot_required is defined and reboot_required.stdout == 'required'
become: false become: false
delegate_to: localhost
when: algo_provider != "local" when: algo_provider != "local"
- name: Include unatteded upgrades configuration - name: Include unatteded upgrades configuration
@ -65,18 +65,21 @@
- meta: flush_handlers - meta: flush_handlers
- name: Check apparmor support - name: Check apparmor support
shell: apparmor_status command: apparmor_status
ignore_errors: yes ignore_errors: yes
changed_when: false
register: apparmor_status register: apparmor_status
- set_fact: - name: Set fact if apparmor enabled
set_fact:
apparmor_enabled: true apparmor_enabled: true
when: '"profiles are in enforce mode" in apparmor_status.stdout' when: '"profiles are in enforce mode" in apparmor_status.stdout'
- name: Gather additional facts - name: Gather additional facts
import_tasks: facts.yml import_tasks: facts.yml
- set_fact: - name: Set OS specific facts
set_fact:
tools: tools:
- git - git
- screen - screen

View file

@ -2,7 +2,7 @@
- name: Install unattended-upgrades - name: Install unattended-upgrades
apt: apt:
name: unattended-upgrades name: unattended-upgrades
state: latest state: present
- name: Configure unattended-upgrades - name: Configure unattended-upgrades
template: template:

View file

@ -36,6 +36,7 @@
- name: Update adblock hosts - name: Update adblock hosts
command: /usr/local/sbin/adblock.sh command: /usr/local/sbin/adblock.sh
changed_when: false
- meta: flush_handlers - meta: flush_handlers

View file

@ -7,13 +7,13 @@
owner: root owner: root
group: root group: root
mode: 0600 mode: 0600
when: apparmor_enabled|default(false)|bool == true when: apparmor_enabled|default(false)|bool
notify: notify:
- restart dnsmasq - restart dnsmasq
- name: Ubuntu | Enforce the dnsmasq AppArmor policy - name: Ubuntu | Enforce the dnsmasq AppArmor policy
shell: aa-enforce usr.sbin.dnsmasq command: aa-enforce usr.sbin.dnsmasq
when: apparmor_enabled|default(false)|bool == true when: apparmor_enabled|default(false)|bool
tags: ['apparmor'] tags: ['apparmor']
- name: Ubuntu | Ensure that the dnsmasq service directory exist - name: Ubuntu | Ensure that the dnsmasq service directory exist

View file

@ -12,7 +12,7 @@
- name: Install dnscrypt-proxy - name: Install dnscrypt-proxy
apt: apt:
name: dnscrypt-proxy name: dnscrypt-proxy
state: latest state: present
update_cache: true update_cache: true
- name: Configure unattended-upgrades - name: Configure unattended-upgrades
@ -37,7 +37,7 @@
command: aa-enforce usr.bin.dnscrypt-proxy command: aa-enforce usr.bin.dnscrypt-proxy
changed_when: false changed_when: false
tags: apparmor tags: apparmor
when: apparmor_enabled|default(false)|bool == true when: apparmor_enabled|default(false)|bool
- name: Ubuntu | Ensure that the dnscrypt-proxy service directory exist - name: Ubuntu | Ensure that the dnscrypt-proxy service directory exist
file: file:

View file

@ -10,7 +10,7 @@
set_fact: set_fact:
cloud_instance_ip: >- cloud_instance_ip: >-
{% if server is defined %}{{ server }} {% if server is defined %}{{ server }}
{%- elif _algo_server.user_input is defined and _algo_server.user_input != "" %}{{ _algo_server.user_input }} {%- elif _algo_server.user_input %}{{ _algo_server.user_input }}
{%- else %}localhost{% endif %} {%- else %}localhost{% endif %}
- pause: - pause:
@ -26,7 +26,7 @@
set_fact: set_fact:
ansible_ssh_user: >- ansible_ssh_user: >-
{% if ssh_user is defined %}{{ ssh_user }} {% if ssh_user is defined %}{{ ssh_user }}
{%- elif _algo_ssh_user.user_input is defined and _algo_ssh_user.user_input != "" %}{{ _algo_ssh_user.user_input }} {%- elif _algo_ssh_user.user_input %}{{ _algo_ssh_user.user_input }}
{%- else %}root{% endif %} {%- else %}root{% endif %}
- pause: - pause:
@ -40,5 +40,5 @@
set_fact: set_fact:
IP_subject_alt_name: >- IP_subject_alt_name: >-
{% if endpoint is defined %}{{ endpoint }} {% if endpoint is defined %}{{ endpoint }}
{%- elif _endpoint.user_input is defined and _endpoint.user_input != "" %}{{ _endpoint.user_input }} {%- elif _endpoint.user_input %}{{ _endpoint.user_input }}
{%- else %}{{ cloud_instance_ip }}{% endif %} {%- else %}{{ cloud_instance_ip }}{% endif %}

View file

@ -42,7 +42,7 @@
file: file:
dest: "{{ ssh_tunnels_config_path }}" dest: "{{ ssh_tunnels_config_path }}"
state: absent state: absent
when: keys_clean_all|bool == True when: keys_clean_all|bool
- name: Ensure the config directories exist - name: Ensure the config directories exist
file: file:

View file

@ -2,7 +2,7 @@
service: name=strongswan state=restarted service: name=strongswan state=restarted
- name: daemon-reload - name: daemon-reload
shell: systemctl daemon-reload systemd: daemon_reload=true
- name: restart apparmor - name: restart apparmor
service: name=apparmor state=restarted service: name=apparmor state=restarted

View file

@ -1,8 +1,13 @@
--- ---
- name: Register p12 PayloadContent - name: Register p12 PayloadContent
shell: cat private/{{ item }}.p12 | base64 shell: |
set -o pipefail
cat private/{{ item }}.p12 |
base64
register: PayloadContent register: PayloadContent
changed_when: false
args: args:
executable: bash
chdir: "{{ ipsec_pki_path }}" chdir: "{{ ipsec_pki_path }}"
with_items: "{{ users }}" with_items: "{{ users }}"

View file

@ -32,8 +32,13 @@
- restart strongswan - restart strongswan
- name: Get loaded plugins - name: Get loaded plugins
shell: > shell: |
find {{ config_prefix|default('/') }}etc/strongswan.d/charon/ -type f -name '*.conf' -exec basename {} \; | cut -f1 -d. set -o pipefail
find {{ config_prefix|default('/') }}etc/strongswan.d/charon/ -type f -name '*.conf' -exec basename {} \; |
cut -f1 -d.
changed_when: false
args:
executable: bash
register: strongswan_plugins register: strongswan_plugins
- name: Disable unneeded plugins - name: Disable unneeded plugins

View file

@ -2,14 +2,19 @@
- block: - block:
- name: Set subjectAltName as a fact - name: Set subjectAltName as a fact
set_fact: set_fact:
subjectAltName: "{{ subjectAltName_IP }}{% if ipv6_support %},IP:{{ ansible_default_ipv6['address'] }}{% endif %}{% if domain and subjectAltName_DNS %},DNS:{{ subjectAltName_DNS }}{% endif %}" subjectAltName: >-
{{ subjectAltName_IP }}
{%- if ipv6_support -%},IP:{{ ansible_default_ipv6['address'] }}{%- endif -%}
{%- if domain and subjectAltName_DNS -%},DNS:{{ subjectAltName_DNS }}{%- endif -%}
tags: always tags: always
- debug: var=subjectAltName
- name: Ensure the pki directory does not exist - name: Ensure the pki directory does not exist
file: file:
dest: "{{ ipsec_pki_path }}" dest: "{{ ipsec_pki_path }}"
state: absent state: absent
when: keys_clean_all|bool == True when: keys_clean_all|bool
- name: Ensure the pki directories exist - name: Ensure the pki directories exist
file: file:
@ -228,11 +233,11 @@
- rereadcrls - rereadcrls
- name: Delete the CA key - name: Delete the CA key
local_action: file:
module: file
path: "{{ ipsec_pki_path }}/private/cakey.pem" path: "{{ ipsec_pki_path }}/private/cakey.pem"
state: absent state: absent
become: false become: false
delegate_to: localhost
when: when:
- ipsec_enabled - ipsec_enabled
- not algo_store_cakey - not algo_store_cakey

View file

@ -1,18 +1,19 @@
--- ---
- name: Set OS specific facts
- set_fact: set_fact:
strongswan_additional_plugins: [] strongswan_additional_plugins: []
- name: Ubuntu | Install strongSwan - name: Ubuntu | Install strongSwan
apt: apt:
name: strongswan name: strongswan
state: latest state: present
update_cache: yes update_cache: yes
install_recommends: yes install_recommends: yes
- name: Ubuntu | Enforcing ipsec with apparmor - name: Ubuntu | Enforcing ipsec with apparmor
shell: aa-enforce "{{ item }}" command: aa-enforce "{{ item }}"
when: apparmor_enabled|default(false)|bool == true when: apparmor_enabled|default(false)|bool
changed_when: false
with_items: with_items:
- /usr/lib/ipsec/charon - /usr/lib/ipsec/charon
- /usr/lib/ipsec/lookip - /usr/lib/ipsec/lookip

View file

@ -1,4 +1,4 @@
conn ikev2-{{ IP_subject_alt_name }} conn algovpn-{{ IP_subject_alt_name }}
fragmentation=yes fragmentation=yes
rekey=no rekey=no
dpdaction=clear dpdaction=clear
@ -16,7 +16,7 @@ conn ikev2-{{ IP_subject_alt_name }}
right={{ IP_subject_alt_name }} right={{ IP_subject_alt_name }}
rightid={{ IP_subject_alt_name }} rightid={{ IP_subject_alt_name }}
rightsubnet=0.0.0.0/0 rightsubnet={{ rightsubnet | default('0.0.0.0/0') }}
rightauth=pubkey rightauth=pubkey
leftsourceip=%config leftsourceip=%config

View file

@ -5,7 +5,7 @@ wireguard_pki_path: "{{ wireguard_config_path }}/.pki/"
wireguard_interface: wg0 wireguard_interface: wg0
keys_clean_all: false keys_clean_all: false
wireguard_dns_servers: >- wireguard_dns_servers: >-
{% if local_dns|default(false)|bool or dns_encryption|default(false)|bool == true %} {% if local_dns|default(false)|bool or dns_encryption|default(false)|bool %}
{{ local_service_ip }} {{ local_service_ip }}
{% else %} {% else %}
{% for host in dns_servers.ipv4 %}{{ host }}{% if not loop.last %},{% endif %}{% endfor %}{% if ipv6_support %},{% for host in dns_servers.ipv6 %}{{ host }}{% if not loop.last %},{% endif %}{% endfor %}{% endif %} {% for host in dns_servers.ipv4 %}{{ host }}{% if not loop.last %},{% endif %}{% endfor %}{% if ipv6_support %},{% for host in dns_servers.ipv6 %}{{ host }}{% if not loop.last %},{% endif %}{% endfor %}{% endif %}

View file

@ -4,7 +4,8 @@
name: wireguard name: wireguard
state: present state: present
- set_fact: - name: Set OS specific facts
set_fact:
service_name: wireguard service_name: wireguard
tags: always tags: always

View file

@ -3,7 +3,7 @@
file: file:
dest: "{{ config_prefix|default('/') }}etc/wireguard/private_{{ item }}.lock" dest: "{{ config_prefix|default('/') }}etc/wireguard/private_{{ item }}.lock"
state: absent state: absent
when: keys_clean_all|bool == True when: keys_clean_all|bool
with_items: with_items:
- "{{ users }}" - "{{ users }}"
- "{{ IP_subject_alt_name }}" - "{{ IP_subject_alt_name }}"
@ -39,7 +39,10 @@
when: wg_genkey.changed when: wg_genkey.changed
- name: Generate public keys - name: Generate public keys
shell: echo "{{ lookup('file', wireguard_pki_path + '/private/' + item) }}" | wg pubkey shell: |
set -o pipefail
echo "{{ lookup('file', wireguard_pki_path + '/private/' + item) }}" |
wg pubkey
register: wg_pubkey register: wg_pubkey
changed_when: false changed_when: false
args: args:

View file

@ -27,6 +27,7 @@
group: root group: root
mode: 0644 mode: 0644
- set_fact: - name: Set OS specific facts
set_fact:
service_name: "wg-quick@{{ wireguard_interface }}" service_name: "wg-quick@{{ wireguard_interface }}"
tags: always tags: always

View file

@ -38,8 +38,7 @@
- block: - block:
- name: Dump the configuration - name: Dump the configuration
local_action: copy:
module: copy
dest: "configs/{{ IP_subject_alt_name }}/.config.yml" dest: "configs/{{ IP_subject_alt_name }}/.config.yml"
content: | content: |
server: {{ 'localhost' if inventory_hostname == 'localhost' else inventory_hostname }} server: {{ 'localhost' if inventory_hostname == 'localhost' else inventory_hostname }}
@ -59,8 +58,12 @@
IP_subject_alt_name: {{ IP_subject_alt_name }} IP_subject_alt_name: {{ IP_subject_alt_name }}
ipsec_enabled: {{ ipsec_enabled }} ipsec_enabled: {{ ipsec_enabled }}
wireguard_enabled: {{ wireguard_enabled }} wireguard_enabled: {{ wireguard_enabled }}
{% if tests|default(false)|bool %}ca_password: {{ CA_password }}{% endif %} {% if tests|default(false)|bool %}
ca_password: {{ CA_password }}
p12_password: {{ p12_export_password }}
{% endif %}
become: false become: false
delegate_to: localhost
- name: Create a symlink if deploying to localhost - name: Create a symlink if deploying to localhost
file: file:

1
tests/algo.conf Normal file
View file

@ -0,0 +1 @@
dhcp-host=algo,10.0.8.100

View file

@ -7,8 +7,9 @@ export ONDEMAND_WIFI_EXCLUDE=test1,test2
export WINDOWS=true export WINDOWS=true
export STORE_CAKEY=true export STORE_CAKEY=true
export LOCAL_DNS=true export LOCAL_DNS=true
export ENDPOINT=algo.lxc export SSH_TUNNELING=true
export USERS=user1,user2 export ENDPOINT=10.0.8.100
export USERS=desktop,user1,user2
export EXTRA_VARS='install_headers=false tests=true apparmor_enabled=false' export EXTRA_VARS='install_headers=false tests=true apparmor_enabled=false'
export ANSIBLE_EXTRA_ARGS='--skip-tags apparmor' export ANSIBLE_EXTRA_ARGS='--skip-tags apparmor'
export REPO_SLUG=${TRAVIS_PULL_REQUEST_SLUG:-${TRAVIS_REPO_SLUG:-trailofbits/algo}} export REPO_SLUG=${TRAVIS_PULL_REQUEST_SLUG:-${TRAVIS_REPO_SLUG:-trailofbits/algo}}

23
tests/ipsec-client.sh Executable file
View file

@ -0,0 +1,23 @@
#!/usr/bin/env bash
set -euxo pipefail
xmllint --noout ./configs/10.0.8.100/ipsec/apple/user1.mobileconfig
ansible-playbook deploy_client.yml \
-e client_ip=localhost \
-e vpn_user=desktop \
-e server_ip=10.0.8.100 \
-e rightsubnet='172.16.0.1/32'
ipsec up algovpn-10.0.8.100
ipsec statusall
ipsec statusall | grep -w ^algovpn-10.0.8.100 | grep -w ESTABLISHED
fping -t 900 -c3 -r3 -Dse 10.0.8.100 172.16.0.1
host google.com 172.16.0.1
echo "IPsec tests passed"

View file

@ -2,11 +2,11 @@
set -ex set -ex
DEPLOY_ARGS="provider=local server=$LXC_IP ssh_user=ubuntu endpoint=$LXC_IP apparmor_enabled=false ondemand_cellular=true ondemand_wifi=true ondemand_wifi_exclude=test local_dns=true ssh_tunneling=true windows=true store_cakey=true install_headers=false tests=true" DEPLOY_ARGS="provider=local server=10.0.8.100 ssh_user=ubuntu endpoint=10.0.8.100 apparmor_enabled=false ondemand_cellular=true ondemand_wifi=true ondemand_wifi_exclude=test local_dns=true ssh_tunneling=true windows=true store_cakey=true install_headers=false tests=true"
if [ "${LXC_NAME}" == "docker" ] if [ "${DEPLOY}" == "docker" ]
then then
docker run -it -v $(pwd)/config.cfg:/algo/config.cfg -v ~/.ssh:/root/.ssh -v $(pwd)/configs:/algo/configs -e "DEPLOY_ARGS=${DEPLOY_ARGS}" travis/algo /bin/sh -c "chown -R 0:0 /root/.ssh && source env/bin/activate && ansible-playbook main.yml -e \"${DEPLOY_ARGS}\" --skip-tags apparmor" docker run -it -v $(pwd)/config.cfg:/algo/config.cfg -v ~/.ssh:/root/.ssh -v $(pwd)/configs:/algo/configs -e "DEPLOY_ARGS=${DEPLOY_ARGS}" travis/algo /bin/sh -c "chown -R root: /root/.ssh && chmod -R 600 /root/.ssh && source env/bin/activate && ansible-playbook main.yml -e \"${DEPLOY_ARGS}\" --skip-tags apparmor"
else else
ansible-playbook main.yml -e "${DEPLOY_ARGS}" --skip-tags apparmor ansible-playbook main.yml -e "${DEPLOY_ARGS}" --skip-tags apparmor
fi fi

View file

@ -1,7 +1,7 @@
USE_LXD_BRIDGE="true" USE_LXD_BRIDGE="true"
LXD_BRIDGE="lxdbr0" LXD_BRIDGE="lxdbr0"
UPDATE_PROFILE="true" UPDATE_PROFILE="true"
LXD_CONFILE="" LXD_CONFILE="/etc/default/algo.conf"
LXD_DOMAIN="lxd" LXD_DOMAIN="lxd"
LXD_IPV4_ADDR="10.0.8.1" LXD_IPV4_ADDR="10.0.8.1"
LXD_IPV4_NETMASK="255.255.255.0" LXD_IPV4_NETMASK="255.255.255.0"
@ -13,4 +13,4 @@ LXD_IPV6_ADDR=""
LXD_IPV6_MASK="" LXD_IPV6_MASK=""
LXD_IPV6_NETWORK="" LXD_IPV6_NETWORK=""
LXD_IPV6_NAT="false" LXD_IPV6_NAT="false"
LXD_IPV6_PROXY="true" LXD_IPV6_PROXY="false"

30
tests/pre-deploy.sh Executable file
View file

@ -0,0 +1,30 @@
#!/usr/bin/env bash
set -euxo pipefail
sysctl net.ipv6.conf.all.disable_ipv6=0
tar xf $HOME/lxc/cache.tar -C / || echo "Didn't extract cache."
cp -f tests/lxd-bridge /etc/default/lxd-bridge
cp -f tests/algo.conf /etc/default/algo.conf
if [[ "$DEPLOY" == "cloud-init" ]]; then
bash tests/cloud-init.sh | lxc profile set default user.user-data -
else
echo -e "#cloud-config\nssh_authorized_keys:\n - $(cat ~/.ssh/id_rsa.pub)" | lxc profile set default user.user-data -
fi
systemctl restart lxd-bridge.service lxd-containers.service lxd.service
lxc profile set default raw.lxc lxc.aa_profile=unconfined
lxc profile set default security.privileged true
lxc profile show default
lxc launch ubuntu:18.04 algo
ip addr
until dig A +short algo.lxd @10.0.8.1 | grep -vE '^$' > /dev/null; do
sleep 3
done
lxc list

15
tests/ssh-tunnel.sh Executable file
View file

@ -0,0 +1,15 @@
#!/usr/bin/env bash
set -euxo pipefail
PASS=$(grep ^p12_password: configs/10.0.8.100/.config.yml | awk '{print $2}')
ssh-keygen -p -P ${PASS} -N '' -f configs/10.0.8.100/ssh-tunnel/desktop.pem
ssh -o StrictHostKeyChecking=no -D 127.0.0.1:1080 -f -q -C -N desktop@10.0.8.100 -i configs/10.0.8.100/ssh-tunnel/desktop.pem
git config --global http.proxy 'socks5://127.0.0.1:1080'
git clone -vv https://github.com/trailofbits/algo /tmp/ssh-tunnel-check
echo "SSH tunneling tests passed"

View file

@ -2,11 +2,11 @@
set -ex set -ex
USER_ARGS="{ 'server': '$LXC_IP', 'users': ['user1', 'user2'] }" USER_ARGS="{ 'server': '10.0.8.100', 'users': ['desktop', 'user1', 'user2'] }"
if [ "${LXC_NAME}" == "docker" ] if [ "${DEPLOY}" == "docker" ]
then then
docker run -it -v $(pwd)/config.cfg:/algo/config.cfg -v ~/.ssh:/root/.ssh -v $(pwd)/configs:/algo/configs -e "USER_ARGS=${USER_ARGS}" travis/algo /bin/sh -c "chown -R 0:0 /root/.ssh && source env/bin/activate && ansible-playbook users.yml -e \"${USER_ARGS}\" -t update-users" docker run -it -v $(pwd)/config.cfg:/algo/config.cfg -v ~/.ssh:/root/.ssh -v $(pwd)/configs:/algo/configs -e "USER_ARGS=${USER_ARGS}" travis/algo /bin/sh -c "chown -R root: /root/.ssh && chmod -R 600 /root/.ssh && source env/bin/activate && ansible-playbook users.yml -e \"${USER_ARGS}\" -t update-users"
else else
ansible-playbook users.yml -e "${USER_ARGS}" -t update-users ansible-playbook users.yml -e "${USER_ARGS}" -t update-users
fi fi
@ -15,7 +15,7 @@ fi
# IPsec # IPsec
# #
if sudo openssl crl -inform pem -noout -text -in configs/$LXC_IP/ipsec/.pki/crl/phone.crt | grep CRL if sudo openssl crl -inform pem -noout -text -in configs/10.0.8.100/ipsec/.pki/crl/phone.crt | grep CRL
then then
echo "The CRL check passed" echo "The CRL check passed"
else else
@ -23,7 +23,7 @@ if sudo openssl crl -inform pem -noout -text -in configs/$LXC_IP/ipsec/.pki/crl/
exit 1 exit 1
fi fi
if sudo openssl x509 -inform pem -noout -text -in configs/$LXC_IP/ipsec/.pki/certs/user1.crt | grep CN=user1 if sudo openssl x509 -inform pem -noout -text -in configs/10.0.8.100/ipsec/.pki/certs/user1.crt | grep CN=user1
then then
echo "The new user exists" echo "The new user exists"
else else
@ -35,7 +35,7 @@ fi
# WireGuard # WireGuard
# #
if sudo test -f configs/$LXC_IP/wireguard/user1.conf if sudo test -f configs/10.0.8.100/wireguard/user1.conf
then then
echo "WireGuard: The new user exists" echo "WireGuard: The new user exists"
else else
@ -47,7 +47,7 @@ fi
# SSH tunneling # SSH tunneling
# #
if sudo test -f configs/$LXC_IP/ssh-tunnel/user1.ssh_config if sudo test -f configs/10.0.8.100/ssh-tunnel/user1.ssh_config
then then
echo "SSH Tunneling: The new user exists" echo "SSH Tunneling: The new user exists"
else else

21
tests/wireguard-client.sh Executable file
View file

@ -0,0 +1,21 @@
#!/usr/bin/env bash
set -euxo pipefail
crudini --set configs/10.0.8.100/wireguard/user1.conf Interface Table off
wg-quick up configs/10.0.8.100/wireguard/user1.conf
wg
ifconfig user1
ip route add 172.16.0.1/32 dev user1
fping -t 900 -c3 -r3 -Dse 10.0.8.100 172.16.0.1
wg | grep "latest handshake"
host google.com 172.16.0.1
echo "WireGuard tests passed"

View file

@ -7,7 +7,8 @@
tasks: tasks:
- block: - block:
- pause: - name: Server address prompt
pause:
prompt: "Enter the IP address of your server: (or use localhost for local installation)" prompt: "Enter the IP address of your server: (or use localhost for local installation)"
register: _server register: _server
when: server is undefined when: server is undefined
@ -16,14 +17,15 @@
set_fact: set_fact:
algo_server: >- algo_server: >-
{% if server is defined %}{{ server }} {% if server is defined %}{{ server }}
{%- elif _server.user_input is defined and _server.user_input != "" %}{{ _server.user_input }} {%- elif _server.user_input %}{{ _server.user_input }}
{%- else %}omit{% endif %} {%- else %}omit{% endif %}
- name: Import host specific variables - name: Import host specific variables
include_vars: include_vars:
file: "configs/{{ algo_server }}/.config.yml" file: "configs/{{ algo_server }}/.config.yml"
- pause: - name: CA password prompt
pause:
prompt: Enter the password for the private CA key prompt: Enter the password for the private CA key
echo: false echo: false
register: _ca_password register: _ca_password
@ -35,7 +37,7 @@
set_fact: set_fact:
CA_password: >- CA_password: >-
{% if ca_password is defined %}{{ ca_password }} {% if ca_password is defined %}{{ ca_password }}
{%- elif _ca_password.user_input is defined and _ca_password.user_input != "" %}{{ _ca_password.user_input }} {%- elif _ca_password.user_input %}{{ _ca_password.user_input }}
{%- else %}omit{% endif %} {%- else %}omit{% endif %}
- name: Add the server to the vpn-host group - name: Add the server to the vpn-host group