merge upstream master

This commit is contained in:
johnwesley 2019-04-27 13:07:39 -04:00
commit c2f283e946
64 changed files with 464 additions and 254 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:
apt:
sources:
sources: &default_sources
- sourceline: 'ppa:ubuntu-lxc/stable'
- sourceline: 'ppa:wireguard/wireguard'
packages:
packages: &default_packages
- python-pip
- lxd
- expect-dev
- debootstrap
- shellcheck
- tree
- bridge-utils
- dnsutils
@ -25,7 +24,12 @@ addons:
- libffi-dev
- python-dev
- linux-headers-$(uname -r)
- wireguard-dkms
- wireguard
- libxml2-utils
- crudini
- fping
- strongswan
- libstrongswan-standard-plugins
cache:
directories:
@ -37,39 +41,54 @@ before_cache:
- sudo tar cf $HOME/lxc/cache.tar /var/lib/lxd/images/
- 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:
fast_finish: true
include:
- stage: Test
name: local deployment from docker
- stage: Tests
name: code checks and linters
addons:
apt:
packages:
- shellcheck
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
- gem install awesome_bot
- ansible-playbook --version
- tree . -L 2
- shellcheck algo install.sh
- 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/update-users.sh
script: *tests
- stage: Test
- stage: Deploy
name: cloud-init deployment
script:
- sudo tar xf $HOME/lxc/cache.tar -C / || echo "Didn't extract cache."
- sudo cp -f tests/lxd-bridge /etc/default/lxd-bridge
- sudo service lxd restart
- bash tests/cloud-init.sh | sudo lxc profile set default user.user-data -
- sudo lxc profile show default
- sudo lxc launch ubuntu:18.04 algo
addons:
apt:
sources: *default_sources
packages: *default_packages
env: DEPLOY=cloud-init
before_install: *provisioning
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
- ( sudo lxc exec algo -- tail -f /var/log/cloud-init-output.log & )
- |
@ -78,11 +97,10 @@ matrix:
sleep 30;
done
- sudo lxc exec algo -- test -f /opt/algo/configs/localhost/.config.yml
# script:
# - 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
# - shellcheck algo
# - ansible-lint main.yml users.yml deploy_client.yml
- sudo lxc exec algo -- tar zcf /root/algo-configs.tar -C /opt/algo/configs/ .
- sudo lxc file pull algo/root/algo-configs.tar ./
- sudo tar -C ./configs -zxf algo-configs.tar
script: *tests
notifications:
email: false

View file

@ -204,6 +204,7 @@ After this process completes, the Algo VPN server will contain only the users li
- Configure [Azure](docs/cloud-azure.md)
- Configure [DigitalOcean](docs/cloud-do.md)
- Configure [Google Cloud Platform](docs/cloud-gce.md)
- Configure [Vultr](docs/cloud-vultr.md)
* Advanced Deployment
- Deploy to your own [FreeBSD](docs/deploy-to-freebsd.md) server
- Deploy to your own [Ubuntu 18.04](docs/deploy-to-ubuntu.md) server

23
algo
View file

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

View file

@ -1,5 +1,7 @@
---
- name: Configure the client
hosts: localhost
become: false
vars_files:
- config.cfg
@ -8,9 +10,10 @@
add_host:
name: "{{ client_ip }}"
groups: client-host
ansible_ssh_user: "{{ ssh_user }}"
ansible_ssh_user: "{{ 'root' if client_ip == 'localhost' else ssh_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
hosts: client-host
@ -18,33 +21,6 @@
become: true
vars_files:
- config.cfg
- roles/vpn/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/strongswan/defaults/main.yml
roles:
- { role: client, tags: ['client'] }
- role: client

View file

@ -2,38 +2,54 @@
## Install WireGuard
To connect to your Algo VPN using [WireGuard](https://www.wireguard.com) from an Ubuntu Server 16.04 (Xenial) or 18.04 (Bionic) client, first install WireGuard on the client:
To connect to your AlgoVPN using [WireGuard](https://www.wireguard.com) from Ubuntu Server, first install WireGuard:
```shell
# Add the WireGuard repository:
sudo add-apt-repository ppa:wireguard/wireguard
# Update the list of available packages (not necessary on Bionic):
# Update the list of available packages (not necessary on Bionic or later):
sudo apt update
# Install the tools and kernel module:
sudo apt install wireguard
```
(For installation on other Linux distributions, see the [Installation](https://www.wireguard.com/install/) page on the WireGuard site.)
For installation on other Linux distributions, see the [Installation](https://www.wireguard.com/install/) page on the WireGuard site.
## Locate the Config File
The Algo-generated config files for WireGuard are named `configs/<ip_address>/wireguard/<username>.conf` on the system where you ran `./algo`. One file was generated for each of the users you added to `config.cfg` before you ran `./algo`. Each Linux and Android client you connect to your Algo VPN must use a different WireGuard config file. Choose one of these files and copy it to your Linux client.
The Algo-generated config files for WireGuard are named `configs/<ip_address>/wireguard/<username>.conf` on the system where you ran `./algo`. One file was generated for each of the users you added to `config.cfg`. Each WireGuard client you connect to your AlgoVPN must use a different config file. Choose one of these files and copy it to your Linux client.
If your client is running Bionic (or another Linux that uses `systemd-resolved` for DNS) you should first edit the config file. Comment out the line that begins with `DNS =` and replace it with:
## Configure DNS
### Ubuntu 18.04 (Bionic)
If your client is running Bionic (or another Linux that uses `systemd-resolved` for DNS but does not have `resolvectl` or `resolvconf` installed) you should first edit the config file. Comment out the line that begins with `DNS =` and replace it with:
```
PostUp = systemd-resolve -i %i --set-dns=172.16.0.1 --set-domain=~.
```
Use the IP address shown on the `DNS =` line (for most, this will be `172.16.0.1`). If the `DNS =` line contains multiple IP addresses, use multiple `--set-dns=` options.
### Ubuntu 18.10 (Cosmic) or 19.04 (Disco)
If your client is running Cosmic or Disco (or another Linux that uses `systemd-resolved` for DNS and has `resolvectl` but *not* `resolvconf` installed) you can either edit the config file as shown above for Bionic or run the following command once:
```
sudo ln -s /usr/bin/resolvectl /usr/bin/resolvconf
```
### Other Linux Distributions
On other Linux distributions you might need to install the `openresolv` package.
## Configure WireGuard
Finally, install the config file on your client as `/etc/wireguard/wg0.conf` and start WireGuard:
```shell
# Install the config file to the WireGuard configuration directory on your
# Bionic or Xenial client:
# Linux client:
sudo install -o root -g root -m 600 <username>.conf /etc/wireguard/wg0.conf
# Start the WireGuard VPN:
@ -42,14 +58,14 @@ sudo systemctl start wg-quick@wg0
# Check that it started properly:
sudo systemctl status wg-quick@wg0
# Verify the connection to the Algo VPN:
# Verify the connection to the AlgoVPN:
sudo wg
# See that your client is using the IP address of your Algo VPN:
# See that your client is using the IP address of your AlgoVPN:
curl ipv4.icanhazip.com
# Optionally configure the connection to come up at boot time:
sudo systemctl enable wg-quick@wg0
```
(If your Linux distribution does not use `systemd`, you can bring up WireGuard with `sudo wg-quick up wg0`).
If your Linux distribution does not use `systemd` you can bring up WireGuard with `sudo wg-quick up wg0`.

View file

@ -1,8 +1,15 @@
### Configuration file
You need to create a configuration file in INI format with your api key (https://my.vultr.com/settings/#settingsapi)
Algo requires an API key from your Vultr account in order to create a server. The API key is generated by going to your Vultr settings at https://my.vultr.com/settings/#settingsapi, and then selecting "generate new API key" on the right side of the box labeled "API Key".
Algo can read the API key in several different ways. Algo will first look for the file containing the API key in the environment variable $VULTR_API_CONFIG if present. You can set this with the command: `export VULTR_API_CONFIG=/path/to/vultr.ini`. Probably the simplest way to give Algo the API key is to create a file titled `.vultr.ini` in your home directory by typing `nano ~/.vultr.ini`, then entering the following text:
```
[default]
key = <your api key>
```
where you've cut-and-pasted the API key from above into the `<your api key>` field (no brackets).
When Algo asks `Enter the local path to your configuration INI file
(https://trailofbits.github.io/algo/cloud-vultr.html):` if you hit enter without typing anything, Algo will look for the file in `~/.vultr.ini` by default.

View file

@ -26,11 +26,12 @@
tasks:
- block:
- pause:
- name: Region prompt
pause:
prompt: |
What provider would you like to use?
{% for p in providers_map %}
{{ loop.index }}. {{ p['name']}}
{{ loop.index }}. {{ p['name'] }}
{% endfor %}
Enter the number of your desired provider
@ -41,7 +42,8 @@
set_fact:
algo_provider: "{{ provider | default(providers_map[_algo_provider.user_input|default(omit)|int - 1]['alias']) }}"
- pause:
- name: VPN server name prompt
pause:
prompt: |
Name the vpn server
[algo]
@ -50,21 +52,24 @@
- server_name is undefined
- algo_provider != "local"
- block:
- pause:
- name: Cellular On Demand prompt
pause:
prompt: |
Do you want macOS/iOS IPsec clients to enable "Connect On Demand" when connected to cellular networks?
[y/N]
register: _ondemand_cellular
when: ondemand_cellular is undefined
- pause:
- name: Wi-Fi On Demand prompt
pause:
prompt: |
Do you want macOS/iOS IPsec clients to enable "Connect On Demand" when connected to Wi-Fi?
[y/N]
register: _ondemand_wifi
when: ondemand_wifi is undefined
- pause:
- name: Trusted Wi-Fi networks prompt
pause:
prompt: |
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)
@ -74,14 +79,16 @@
- (ondemand_wifi|default(false)|bool) or
(booleans_map[_ondemand_wifi.user_input|default(omit)]|default(false))
- pause:
- name: Compatible ciphers prompt
pause:
prompt: |
Do you want the VPN to support Windows 10 or Linux Desktop clients? (enables compatible ciphers and key exchange, less secure)
[y/N]
register: _windows
when: windows is undefined
- pause:
- name: Retain the CA key prompt
pause:
prompt: |
Do you want to retain the CA key? (required to add users in the future, but less secure)
[y/N]
@ -89,14 +96,16 @@
when: store_cakey is undefined
when: ipsec_enabled
- pause:
- name: DNS adblocking prompt
pause:
prompt: |
Do you want to install an ad blocking DNS resolver on this VPN server?
[y/N]
register: _local_dns
when: local_dns is undefined
- pause:
- name: SSH tunneling prompt
pause:
prompt: |
Do you want each user to have their own account for SSH tunneling?
[y/N]
@ -107,36 +116,38 @@
set_fact:
algo_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 -%}
{{ _server | regex_replace('(?!\.)(\W|_)', '-') }}
algo_ondemand_cellular: >-
{% 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 %}
algo_ondemand_wifi: >-
{% 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 %}
algo_ondemand_wifi_exclude: >-
{% 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 %}
algo_local_dns: >-
{% 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 %}
algo_ssh_tunneling: >-
{% 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 %}
algo_windows: >-
{% 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 %}
algo_store_cakey: >-
{% 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 %}
rescue:
- include_tasks: playbooks/rescue.yml
- include_tasks: playbooks/rescue.yml

View file

@ -36,12 +36,11 @@ installRequirements() {
}
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
git checkout ${REPO_BRANCH}
python -m virtualenv --python=`which python2` .venv
python -m virtualenv --python="$(command -v python2)" .venv
# shellcheck source=/dev/null
. .venv/bin/activate
python -m pip install -U pip virtualenv
python -m pip install -r requirements.txt
@ -50,27 +49,23 @@ getAlgo() {
publicIpFromInterface() {
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}')"
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
echo "Using ${ENDPOINT} as the endpoint"
}
publicIpFromMetadata() {
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)"
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)"
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")"
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')"
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
echo "Using ${ENDPOINT} as the endpoint"
else
@ -82,23 +77,25 @@ deployAlgo() {
getAlgo
cd /opt/algo
# shellcheck source=/dev/null
. .venv/bin/activate
export HOME=/root
export ANSIBLE_LOCAL_TEMP=/root/.ansible/tmp
export ANSIBLE_REMOTE_TEMP=/root/.ansible/tmp
# shellcheck disable=SC2086
ansible-playbook main.yml \
-e provider=local \
-e ondemand_cellular=${ONDEMAND_CELLULAR} \
-e ondemand_wifi=${ONDEMAND_WIFI} \
-e ondemand_wifi_exclude=${ONDEMAND_WIFI_EXCLUDE} \
-e windows=${WINDOWS} \
-e store_cakey=${STORE_CAKEY} \
-e local_dns=${LOCAL_DNS} \
-e ssh_tunneling=${SSH_TUNNELING} \
-e endpoint=$ENDPOINT \
-e users=$(echo "$USERS" | jq -Rc 'split(",")') \
-e "ondemand_cellular=${ONDEMAND_CELLULAR}" \
-e "ondemand_wifi=${ONDEMAND_WIFI}" \
-e "ondemand_wifi_exclude=${ONDEMAND_WIFI_EXCLUDE}" \
-e "windows=${WINDOWS}" \
-e "store_cakey=${STORE_CAKEY}" \
-e "local_dns=${LOCAL_DNS}" \
-e "ssh_tunneling=${SSH_TUNNELING}" \
-e "endpoint=$ENDPOINT" \
-e "users=$(echo "$USERS" | jq -Rc 'split(",")')" \
-e server=localhost \
-e ssh_user=root \
-e "${EXTRA_VARS}" \
@ -106,7 +103,7 @@ deployAlgo() {
tee /var/log/algo.log
}
if test $METHOD = "cloud"; then
if test "$METHOD" = "cloud"; then
publicIpFromMetadata
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
import_playbook: input.yml

View file

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

View file

@ -2,4 +2,5 @@
- debug:
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
service: name=strongswan state=restarted

View file

@ -8,13 +8,21 @@
package: name="{{ item }}" state=present
with_items:
- "{{ prerequisites }}"
register: result
until: result is succeeded
retries: 10
delay: 3
- name: Install strongSwan
package: name=strongswan state=present
register: result
until: result is succeeded
retries: 10
delay: 3
- name: Setup the ipsec config
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"
mode: '0644'
with_items:
@ -24,7 +32,7 @@
- name: Setup the ipsec secrets
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"
mode: '0600'
with_items:

View file

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

View file

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

View file

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

View file

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

View file

@ -9,14 +9,14 @@
- set_fact:
algo_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 %}
- name: Create AlgoVPN Server
azure_rm_deployment:
state: present
deployment_name: "{{ algo_server_name }}"
template: "{{ lookup('file', 'deployment.json') }}"
template: "{{ lookup('file', role_path + '/files/deployment.json') }}"
secret: "{{ secret }}"
tenant: "{{ tenant }}"
client_id: "{{ client_id }}"

View file

@ -10,23 +10,32 @@
name:
- packaging
- requests[security]
- azure-mgmt-compute>=2.0.0,<3
- azure-mgmt-network>=1.3.0,<2
- azure-mgmt-storage>=1.5.0,<2
- azure-mgmt-resource>=1.1.0,<2
- azure-storage>=0.35.1,<0.36
- azure-cli-core>=2.0.12,<3
- azure-cli-core==2.0.35
- azure-cli-nspkg==3.0.2
- azure-common==1.1.11
- azure-mgmt-batch==4.1.0
- azure-mgmt-compute==2.1.0
- 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
- msrestazure==0.4.31
- azure-mgmt-dns>=1.0.1,<2
- azure-mgmt-keyvault>=0.40.0,<0.41
- 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
- azure-keyvault==1.0.0a1
- azure-graphrbac==0.40.0
state: latest
virtualenv: "{{ azure_venv }}"
virtualenv_python: python2.7

View file

@ -10,7 +10,7 @@
set_fact:
algo_do_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 %}
public_key: "{{ lookup('file', '{{ SSH_keys.public }}') }}"
@ -22,7 +22,7 @@
api_token: "{{ algo_do_token }}"
name: "{{ SSH_keys.comment }}"
register: ssh_keys
until: ssh_keys.changed != true
until: not ssh_keys.changed
retries: 10
delay: 1
@ -83,7 +83,7 @@
api_token: "{{ algo_do_token }}"
name: "{{ SSH_keys.comment }}"
register: ssh_keys
until: ssh_keys.changed != true
until: not ssh_keys.changed
retries: 10
delay: 1

View file

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

View file

@ -9,7 +9,7 @@
- set_fact:
algo_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 %}
stack_name: "{{ algo_server_name | replace('.', '-') }}"

View file

@ -63,5 +63,5 @@
- set_fact:
algo_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 %}

View file

@ -57,5 +57,5 @@
- set_fact:
algo_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 %}

View file

@ -1,7 +1,7 @@
---
- 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)"
when: lookup('env', 'OS_AUTH_URL') == ""
when: lookup('env', 'OS_AUTH_URL')|length <= 0
- name: Build python virtual environment
import_tasks: venv.yml

View file

@ -84,7 +84,7 @@
organization: "{{ organization_id }}"
name: "{{ algo_server_name }}"
image: "{{ image_id }}"
commercial_type: "{{cloud_providers.scaleway.size }}"
commercial_type: "{{ cloud_providers.scaleway.size }}"
enable_ipv6: true
boot_type: local
tags:

View file

@ -30,5 +30,5 @@
algo_scaleway_org: "{{ scaleway_org | default(_scaleway_org.user_input|default(omit)) }}"
algo_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 %}

View file

@ -1,21 +1,43 @@
---
- block:
- name: Include prompts
import_tasks: prompts.yml
- name: Include prompts
import_tasks: prompts.yml
- block:
- name: Upload the SSH key
vr_ssh_key:
vultr_ssh_key:
name: "{{ SSH_keys.comment }}"
ssh_key: "{{ lookup('file', '{{ SSH_keys.public }}') }}"
register: ssh_key
- name: Creating a firewall group
vultr_firewall_group:
name: "{{ algo_server_name }}"
- name: Creating firewall rules
vultr_firewall_rule:
group: "{{ algo_server_name }}"
protocol: "{{ item.protocol }}"
port: "{{ item.port }}"
ip_version: "{{ item.ip }}"
cidr: "{{ item.cidr }}"
with_items:
- { protocol: tcp, port: 22, ip: v4, cidr: "0.0.0.0/0" }
- { protocol: tcp, port: 22, ip: v6, cidr: "::/0" }
- { protocol: udp, port: 500, ip: v4, cidr: "0.0.0.0/0" }
- { protocol: udp, port: 500, ip: v6, cidr: "::/0" }
- { protocol: udp, port: 4500, ip: v4, cidr: "0.0.0.0/0" }
- { protocol: udp, port: 4500, ip: v6, cidr: "::/0" }
- { protocol: udp, port: "{{ wireguard_port }}", ip: v4, cidr: "0.0.0.0/0" }
- { protocol: udp, port: "{{ wireguard_port }}", ip: v6, cidr: "::/0" }
- name: Creating a server
vr_server:
vultr_server:
name: "{{ algo_server_name }}"
hostname: "{{ algo_server_name }}"
os: "{{ cloud_providers.vultr.os }}"
plan: "{{ cloud_providers.vultr.size }}"
region: "{{ algo_vultr_region }}"
firewall_group: "{{ algo_server_name }}"
state: started
tag: Environment:Algo
ssh_key: "{{ ssh_key.vultr_ssh_key.name }}"

View file

@ -54,5 +54,5 @@
set_fact:
algo_vultr_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 %}

View file

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

View file

@ -1,26 +1,26 @@
---
- block:
- name: Generate password for the CA key
local_action:
module: shell
openssl rand -hex 16
command: openssl rand -hex 16
register: CA_password
- name: Generate p12 export password
local_action:
module: shell
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())]))'
shell: >
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())]))'
register: p12_password_generated
when: p12_password is not defined
tags: update-users
become: false
delegate_to: localhost
- name: Define facts
set_fact:
p12_export_password: "{{ p12_password|default(p12_password_generated.stdout) }}"
tags: update-users
- set_fact:
- name: Set facts
set_fact:
CA_password: "{{ CA_password.stdout }}"
IP_subject_alt_name: "{{ IP_subject_alt_name }}"
@ -31,5 +31,5 @@
- name: Check size of MTU
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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -12,7 +12,7 @@
- name: Install dnscrypt-proxy
apt:
name: dnscrypt-proxy
state: latest
state: present
update_cache: true
- name: Configure unattended-upgrades
@ -37,7 +37,7 @@
command: aa-enforce usr.bin.dnscrypt-proxy
changed_when: false
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
file:

View file

@ -10,7 +10,7 @@
set_fact:
cloud_instance_ip: >-
{% 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 %}
- pause:
@ -26,7 +26,7 @@
set_fact:
ansible_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 %}
- pause:
@ -40,5 +40,5 @@
set_fact:
IP_subject_alt_name: >-
{% 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 %}

View file

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

View file

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

View file

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

View file

@ -32,8 +32,13 @@
- restart strongswan
- name: Get loaded plugins
shell: >
find {{ config_prefix|default('/') }}etc/strongswan.d/charon/ -type f -name '*.conf' -exec basename {} \; | cut -f1 -d.
shell: |
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
- name: Disable unneeded plugins

View file

@ -2,14 +2,19 @@
- block:
- name: Set subjectAltName as a 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
- debug: var=subjectAltName
- name: Ensure the pki directory does not exist
file:
dest: "{{ ipsec_pki_path }}"
state: absent
when: keys_clean_all|bool == True
when: keys_clean_all|bool
- name: Ensure the pki directories exist
file:
@ -182,7 +187,7 @@
awk '{print $5}' |
sed 's/\/CN=//g'
args:
chdir: "{{ ipsec_pki_path}}"
chdir: "{{ ipsec_pki_path }}"
register: valid_certs
- name: Revoke non-existing users
@ -228,11 +233,11 @@
- rereadcrls
- name: Delete the CA key
local_action:
module: file
file:
path: "{{ ipsec_pki_path }}/private/cakey.pem"
state: absent
become: false
delegate_to: localhost
when:
- ipsec_enabled
- not algo_store_cakey

View file

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

View file

@ -1,4 +1,4 @@
conn ikev2-{{ IP_subject_alt_name }}
conn algovpn-{{ IP_subject_alt_name }}
fragmentation=yes
rekey=no
dpdaction=clear
@ -16,7 +16,7 @@ conn ikev2-{{ IP_subject_alt_name }}
right={{ 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
leftsourceip=%config

View file

@ -5,7 +5,7 @@ wireguard_pki_path: "{{ wireguard_config_path }}/.pki/"
wireguard_interface: wg0
keys_clean_all: false
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 }}
{% 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 %}

View file

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

View file

@ -3,7 +3,7 @@
file:
dest: "{{ config_prefix|default('/') }}etc/wireguard/private_{{ item }}.lock"
state: absent
when: keys_clean_all|bool == True
when: keys_clean_all|bool
with_items:
- "{{ users }}"
- "{{ IP_subject_alt_name }}"
@ -39,7 +39,10 @@
when: wg_genkey.changed
- 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
changed_when: false
args:

View file

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

View file

@ -38,8 +38,7 @@
- block:
- name: Dump the configuration
local_action:
module: copy
copy:
dest: "configs/{{ IP_subject_alt_name }}/.config.yml"
content: |
server: {{ 'localhost' if inventory_hostname == 'localhost' else inventory_hostname }}
@ -59,8 +58,12 @@
IP_subject_alt_name: {{ IP_subject_alt_name }}
ipsec_enabled: {{ ipsec_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
delegate_to: localhost
- name: Create a symlink if deploying to localhost
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 STORE_CAKEY=true
export LOCAL_DNS=true
export ENDPOINT=algo.lxc
export USERS=user1,user2
export SSH_TUNNELING=true
export ENDPOINT=10.0.8.100
export USERS=desktop,user1,user2
export EXTRA_VARS='install_headers=false tests=true apparmor_enabled=false'
export ANSIBLE_EXTRA_ARGS='--skip-tags apparmor'
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,15 @@
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
<<<<<<< HEAD
make docker-test-local
=======
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"
>>>>>>> upstream/master
else
ansible-playbook main.yml -e "${DEPLOY_ARGS}" --skip-tags apparmor
fi

View file

@ -1,7 +1,7 @@
USE_LXD_BRIDGE="true"
LXD_BRIDGE="lxdbr0"
UPDATE_PROFILE="true"
LXD_CONFILE=""
LXD_CONFILE="/etc/default/algo.conf"
LXD_DOMAIN="lxd"
LXD_IPV4_ADDR="10.0.8.1"
LXD_IPV4_NETMASK="255.255.255.0"
@ -13,4 +13,4 @@ LXD_IPV6_ADDR=""
LXD_IPV6_MASK=""
LXD_IPV6_NETWORK=""
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
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
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
ansible-playbook users.yml -e "${USER_ARGS}" -t update-users
fi
@ -15,7 +15,7 @@ fi
# 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
echo "The CRL check passed"
else
@ -23,7 +23,7 @@ if sudo openssl crl -inform pem -noout -text -in configs/$LXC_IP/ipsec/.pki/crl/
exit 1
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
echo "The new user exists"
else
@ -35,7 +35,7 @@ fi
# WireGuard
#
if sudo test -f configs/$LXC_IP/wireguard/user1.conf
if sudo test -f configs/10.0.8.100/wireguard/user1.conf
then
echo "WireGuard: The new user exists"
else
@ -47,7 +47,7 @@ fi
# 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
echo "SSH Tunneling: The new user exists"
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:
- block:
- pause:
- name: Server address prompt
pause:
prompt: "Enter the IP address of your server: (or use localhost for local installation)"
register: _server
when: server is undefined
@ -16,14 +17,15 @@
set_fact:
algo_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 %}
- name: Import host specific variables
include_vars:
file: "configs/{{ algo_server }}/.config.yml"
- pause:
- name: CA password prompt
pause:
prompt: Enter the password for the private CA key
echo: false
register: _ca_password
@ -35,7 +37,7 @@
set_fact:
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 %}
- name: Add the server to the vpn-host group