mirror of
https://github.com/trailofbits/algo.git
synced 2025-08-09 14:23:05 +02:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
1f4964649f
53 changed files with 1104 additions and 488 deletions
111
.travis.yml
111
.travis.yml
|
@ -51,56 +51,73 @@ custom_scripts:
|
|||
- sudo env "PATH=$PATH" ./tests/ipsec-client.sh
|
||||
- sudo ./tests/ssh-tunnel.sh
|
||||
|
||||
stages:
|
||||
- &tests-and-linters
|
||||
stage: Tests
|
||||
name: code checks and linters
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- shellcheck
|
||||
script:
|
||||
- pip install ansible-lint
|
||||
- shellcheck algo install.sh
|
||||
- ansible-playbook main.yml --syntax-check
|
||||
- ansible-lint -v *.yml
|
||||
|
||||
- &deploy-local
|
||||
stage: Deploy
|
||||
name: local deployment from docker
|
||||
addons:
|
||||
apt:
|
||||
sources: *default_sources
|
||||
packages: *default_packages
|
||||
before_install: *provisioning
|
||||
before_script:
|
||||
- docker build -t travis/algo .
|
||||
- ./tests/local-deploy.sh
|
||||
- ./tests/update-users.sh
|
||||
script: *tests
|
||||
|
||||
- &deploy-cloudinit
|
||||
stage: Deploy
|
||||
name: cloud-init deployment
|
||||
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 & )
|
||||
- |
|
||||
until sudo lxc exec algo -- test -f /var/lib/cloud/data/result.json; do
|
||||
echo 'Cloud init is not finished. Sleep for 30 seconds';
|
||||
sleep 30;
|
||||
done
|
||||
- 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/ .
|
||||
- sudo lxc file pull algo/root/algo-configs.tar ./
|
||||
- sudo tar -C ./configs -zxf algo-configs.tar
|
||||
script: *tests
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
- stage: Tests
|
||||
name: code checks and linters
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- shellcheck
|
||||
script:
|
||||
- pip install ansible-lint
|
||||
- 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: Deploy
|
||||
name: cloud-init deployment
|
||||
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 & )
|
||||
- |
|
||||
until sudo lxc exec algo -- test -f /var/lib/cloud/data/result.json; do
|
||||
echo 'Cloud init is not finished. Sleep for 30 seconds';
|
||||
sleep 30;
|
||||
done
|
||||
- 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/ .
|
||||
- sudo lxc file pull algo/root/algo-configs.tar ./
|
||||
- sudo tar -C ./configs -zxf algo-configs.tar
|
||||
script: *tests
|
||||
- <<: *tests-and-linters
|
||||
- <<: *deploy-local
|
||||
name: 'Ubuntu 18.04: local deployment from docker'
|
||||
env: DEPLOY=docker UBUNTU_VERSION=18.04
|
||||
- <<: *deploy-local
|
||||
name: 'Ubuntu 19.04: local deployment from docker'
|
||||
env: DEPLOY=docker UBUNTU_VERSION=19.04
|
||||
- <<: *deploy-cloudinit
|
||||
name: 'Ubuntu 18.04: cloud-init deployment'
|
||||
env: DEPLOY=cloud-init UBUNTU_VERSION=18.04
|
||||
- <<: *deploy-cloudinit
|
||||
name: 'Ubuntu 19.04: cloud-init deployment'
|
||||
env: DEPLOY=cloud-init UBUNTU_VERSION=19.04
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
|
|
24
CHANGELOG.md
24
CHANGELOG.md
|
@ -1,10 +1,30 @@
|
|||
## 1.1 (Unreleased)
|
||||
## 1.1 [(Unreleased)](https://github.com/trailofbits/algo/tree/HEAD)
|
||||
|
||||
### Added
|
||||
- Support for Ubuntu 19.04 [\#1405](https://github.com/trailofbits/algo/pull/1405) ([jackivanov](https://github.com/jackivanov))
|
||||
- AWS support for existing EIP [\#1292](https://github.com/trailofbits/algo/pull/1292) ([statik](https://github.com/statik))
|
||||
- Script to support cloud-init and local easy deploy [\#1366](https://github.com/trailofbits/algo/pull/1366) ([jackivanov](https://github.com/jackivanov))
|
||||
- Automatically create cloud firewall rules for installs onto Vultr [\#1400](https://github.com/trailofbits/algo/pull/1400) ([TC1977](https://github.com/TC1977))
|
||||
- Randomly generated IP address for the local dns resolver [\#1429](https://github.com/trailofbits/algo/pull/1429) ([jackivanov](https://github.com/jackivanov))
|
||||
- Update users: add server pick-list [\#1441](https://github.com/trailofbits/algo/pull/1441) ([TC1977](https://github.com/TC1977))
|
||||
- Additional testing [\#213](https://github.com/trailofbits/algo/issues/213)
|
||||
- Add IPv6 support to DNS [\#1425](https://github.com/trailofbits/algo/pull/1425) ([shapiro125](https://github.com/shapiro125))
|
||||
- Additional p12 with the CA cert included [\#1403](https://github.com/trailofbits/algo/pull/1403) ([jackivanov](https://github.com/jackivanov))
|
||||
|
||||
### Fixed
|
||||
- Fixes error in 10-algo-lo100.network [\#1369](https://github.com/trailofbits/algo/pull/1369) ([adamluk](https://github.com/adamluk))
|
||||
- Error message is missing for some roles [\#1364](https://github.com/trailofbits/algo/issues/1364)
|
||||
- DNS leak in Linux/Wireguard when LAN gateway/DNS is 172.16.0.1 [\#1422](https://github.com/trailofbits/algo/issues/1422)
|
||||
- Installation error after \#1397 [\#1409](https://github.com/trailofbits/algo/issues/1409)
|
||||
|
||||
## 1.0 (Mar 19, 2019)
|
||||
### Changed
|
||||
- Refactoring, Linting and additional tests [\#1397](https://github.com/trailofbits/algo/pull/1397) ([jackivanov](https://github.com/jackivanov))
|
||||
- Scaleway modules [\#1410](https://github.com/trailofbits/algo/pull/1410) ([jackivanov](https://github.com/jackivanov))
|
||||
- Use VULTR_API_CONFIG variable if set [\#1374](https://github.com/trailofbits/algo/pull/1374) ([davidemyers](https://github.com/davidemyers))
|
||||
- Simplify Apple Profile Configuration Template [\#1033](https://github.com/trailofbits/algo/pull/1033) ([faf0](https://github.com/faf0))
|
||||
- Include roles as separate tasks [\#1365](https://github.com/trailofbits/algo/pull/1365) ([jackivanov](https://github.com/jackivanov))
|
||||
|
||||
## 1.0 [(Mar 19, 2019)](https://github.com/trailofbits/algo/tree/v1.0)
|
||||
|
||||
### Added
|
||||
- Tagged releases and changelog [\#724](https://github.com/trailofbits/algo/issues/724)
|
||||
|
|
59
README.md
59
README.md
|
@ -14,7 +14,7 @@ Algo VPN is a set of Ansible scripts that simplify the setup of a personal IPSEC
|
|||
* Blocks ads with a local DNS resolver (optional)
|
||||
* Sets up limited SSH users for tunneling traffic (optional)
|
||||
* Based on current versions of Ubuntu and strongSwan
|
||||
* Installs to DigitalOcean, Amazon Lightsail, Amazon EC2, Vultr, Microsoft Azure, Google Compute Engine, Scaleway, OpenStack, or your own Ubuntu 18.04 LTS server
|
||||
* Installs to DigitalOcean, Amazon Lightsail, Amazon EC2, Vultr, Microsoft Azure, Google Compute Engine, Scaleway, OpenStack, or your own Ubuntu server
|
||||
|
||||
## Anti-features
|
||||
|
||||
|
@ -51,7 +51,7 @@ The easiest way to get an Algo server running is to let it set up a _new_ virtua
|
|||
python-setuptools \
|
||||
python-virtualenv -y
|
||||
```
|
||||
- Linux (rpm-based): See the [Pre-Install Documentation for RedHat/CentOS 6.x](docs/deploy-from-redhat-centos6.md)
|
||||
- Linux (rpm-based): See the pre-installation documentation for [RedHat/CentOS 6.x](docs/deploy-from-redhat-centos6.md) or [Fedora](docs/deploy-from-fedora-workstation.md)
|
||||
- Windows: See the [Windows documentation](docs/deploy-from-windows.md)
|
||||
|
||||
4. **Install Algo's remaining dependencies.** Use the same Terminal window as the previous step and run:
|
||||
|
@ -72,15 +72,15 @@ That's it! You will get the message below when the server deployment process com
|
|||
You can now setup clients to connect it, e.g. your iPhone or laptop. Proceed to [Configure the VPN Clients](#configure-the-vpn-clients) below.
|
||||
|
||||
```
|
||||
"\"#----------------------------------------------------------------------#\"",
|
||||
"\"# Congratulations! #\"",
|
||||
"\"# Your Algo server is running. #\"",
|
||||
"\"# Config files and certificates are in the ./configs/ directory. #\"",
|
||||
"\"# Go to https://whoer.net/ after connecting #\"",
|
||||
"\"# and ensure that all your traffic passes through the VPN. #\"",
|
||||
"\"# Local DNS resolver 172.16.0.1 #\"",
|
||||
"\"# The p12 and SSH keys password is XXXXXXXX #\"",
|
||||
"\"#----------------------------------------------------------------------#\"",
|
||||
"# Congratulations! #"
|
||||
"# Your Algo server is running. #"
|
||||
"# Config files and certificates are in the ./configs/ directory. #"
|
||||
"# Go to https://whoer.net/ after connecting #"
|
||||
"# and ensure that all your traffic passes through the VPN. #"
|
||||
"# Local DNS resolver 172.16.0.1 #"
|
||||
"# The p12 and SSH keys password for new users is XXXXXXXX #"
|
||||
"# The CA key password is XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #"
|
||||
"# Shell access: ssh -i configs/algo.pem root@xxx.xxx.xx.xx #"
|
||||
```
|
||||
|
||||
## Configure the VPN Clients
|
||||
|
@ -93,9 +93,9 @@ WireGuard is used to provide VPN services on Apple devices. Algo generates a Wir
|
|||
|
||||
On iOS, install the [WireGuard](https://itunes.apple.com/us/app/wireguard/id1441195209?mt=8) app from the iOS App Store. Then, use the WireGuard app to scan the QR code or AirDrop the configuration file to the device.
|
||||
|
||||
On macOS Mojave or later, install the [WireGuard](https://itunes.apple.com/us/app/wireguard/id1451685025?mt=12) app from the Mac App Store. WireGuard will appear in the menu bar once you run the app. Click on the WireGuard icon, choose **Import tunnel(s) from file...**, then select the appropriate WireGuard configuration file.
|
||||
On macOS Mojave or later, install the [WireGuard](https://itunes.apple.com/us/app/wireguard/id1451685025?mt=12) app from the Mac App Store. WireGuard will appear in the menu bar once you run the app. Click on the WireGuard icon, choose **Import tunnel(s) from file...**, then select the appropriate WireGuard configuration file.
|
||||
|
||||
On either iOS or macOS, you can enable "Connect on Demand" and/or exclude certain trusted Wi-Fi networks (such as your home or work) by editing the tunnel configuration in the WireGuard app. (Algo can't do this automatically for you.)
|
||||
On either iOS or macOS, you can enable "Connect on Demand" and/or exclude certain trusted Wi-Fi networks (such as your home or work) by editing the tunnel configuration in the WireGuard app. (Algo can't do this automatically for you.)
|
||||
|
||||
Installing WireGuard is a little more complicated on older version of macOS. See [Using macOS as a Client with WireGuard](docs/client-macos-wireguard.md).
|
||||
|
||||
|
@ -122,7 +122,7 @@ Network Manager does not support AES-GCM. In order to support Linux Desktop clie
|
|||
|
||||
Install strongSwan, then copy the included ipsec_user.conf, ipsec_user.secrets, user.crt (user certificate), and user.key (private key) files to your client device. These will require customization based on your exact use case. These files were originally generated with a point-to-point OpenWRT-based VPN in mind.
|
||||
|
||||
#### Ubuntu Server 18.04 example
|
||||
#### Ubuntu Server example
|
||||
|
||||
1. `sudo apt-get install strongswan libstrongswan-standard-plugins`: install strongSwan
|
||||
2. `/etc/ipsec.d/certs`: copy `<name>.crt` from `algo-master/configs/<server_ip>/ipsec/manual/<name>.crt`
|
||||
|
@ -166,16 +166,14 @@ Use the example command below to start an SSH tunnel by replacing `user` and `ip
|
|||
|
||||
## SSH into Algo Server
|
||||
|
||||
To SSH into the Algo server for administrative purposes you can use the example command below by replacing `ip` with your own:
|
||||
Your Algo server is configured for key-only SSH access for administrative purposes. Open the Terminal app, `cd` into the `algo-master` directory where you originally downloaded Algo, and then use the command listed on the success message:
|
||||
|
||||
`ssh root@ip -i ~/.ssh/algo.pem`
|
||||
`ssh -i configs/algo.pem user@ip`
|
||||
|
||||
If you find yourself regularly logging into Algo then it will be useful to load your Algo ssh key automatically. Add the following snippet to the bottom of `~/.bash_profile` to add it to your shell environment permanently.
|
||||
where `user` is either `root` or `ubuntu` as listed on the success message, and `ip` is the IP address of your Algo server. If you find yourself regularly logging into the server then it will be useful to load your Algo ssh key automatically. Add the following snippet to the bottom of `~/.bash_profile` to add it to your shell environment permanently.
|
||||
|
||||
`ssh-add ~/.ssh/algo > /dev/null 2>&1`
|
||||
|
||||
Note the admin username is `ubuntu` instead of `root` on providers other than Digital Ocean.
|
||||
|
||||
## Adding or Removing Users
|
||||
|
||||
If you chose to save the CA certificate during the deploy process, then Algo's own scripts can easily add and remove users from the VPN server.
|
||||
|
@ -187,28 +185,7 @@ If you chose to save the CA certificate during the deploy process, then Algo's o
|
|||
After this process completes, the Algo VPN server will contain only the users listed in the `config.cfg` file.
|
||||
|
||||
## Additional Documentation
|
||||
|
||||
* Setup instructions
|
||||
- Documentation for available [Ansible roles](docs/setup-roles.md)
|
||||
- Deploy from [Fedora Workstation (26)](docs/deploy-from-fedora-workstation.md)
|
||||
- Deploy from [RedHat/CentOS 6.x](docs/deploy-from-redhat-centos6.md)
|
||||
- Deploy from [Windows](docs/deploy-from-windows.md)
|
||||
- Deploy from [Ansible](docs/deploy-from-ansible.md) directly
|
||||
* Client setup
|
||||
- Setup [Android](docs/client-android.md) clients
|
||||
- Setup [Generic/Linux](docs/client-linux.md) clients with Ansible
|
||||
- Setup Ubuntu clients to use [WireGuard](docs/client-linux-wireguard.md)
|
||||
- Setup Apple devices to use [IPSEC](docs/client-apple-ipsec.md)
|
||||
* Cloud setup
|
||||
- Configure [Amazon EC2](docs/cloud-amazon-ec2.md)
|
||||
- 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
|
||||
- Deploy to an [unsupported cloud provider](docs/deploy-to-unsupported-cloud.md)
|
||||
* [Deployment instructions, cloud provider setup instructions, and further client setup instructions available here.](docs/index.md)
|
||||
* [FAQ](docs/faq.md)
|
||||
* [Troubleshooting](docs/troubleshooting.md)
|
||||
|
||||
|
|
51
config.cfg
51
config.cfg
|
@ -1,15 +1,14 @@
|
|||
---
|
||||
|
||||
# This is the list of user to generate.
|
||||
# This is the list of users to generate.
|
||||
# Every device must have a unique username.
|
||||
# You can generate up to 250 users at one time.
|
||||
# Usernames with leading 0's or containing only numbers should be escaped in double quotes, e.g. "000dan" or "123".
|
||||
users:
|
||||
- phone
|
||||
- laptop
|
||||
- desktop
|
||||
|
||||
# NOTE: You must "escape" any usernames with leading 0's, like "000dan"
|
||||
|
||||
### Advanced users only below this line ###
|
||||
|
||||
# If True re-init all existing certificates. Boolean
|
||||
|
@ -40,20 +39,8 @@ wireguard_port: 51820
|
|||
wireguard_PersistentKeepalive: 0
|
||||
|
||||
# WireGuard network configuration
|
||||
_wireguard_network_ipv4:
|
||||
subnet: 10.19.49.0
|
||||
prefix: 24
|
||||
gateway: 10.19.49.1
|
||||
clients_range: 10.19.49
|
||||
clients_start: 2
|
||||
_wireguard_network_ipv6:
|
||||
subnet: 'fd9d:bc11:4021::'
|
||||
prefix: 48
|
||||
gateway: 'fd9d:bc11:4021::1'
|
||||
clients_range: 'fd9d:bc11:4021::'
|
||||
clients_start: 2
|
||||
wireguard_network_ipv4: "{{ _wireguard_network_ipv4['subnet'] }}/{{ _wireguard_network_ipv4['prefix'] }}"
|
||||
wireguard_network_ipv6: "{{ _wireguard_network_ipv6['subnet'] }}/{{ _wireguard_network_ipv6['prefix'] }}"
|
||||
wireguard_network_ipv4: 10.19.49.0/24
|
||||
wireguard_network_ipv6: fd9d:bc11:4021::/48
|
||||
|
||||
# Reduce the MTU of the VPN tunnel
|
||||
# Some cloud and internet providers use a smaller MTU (Maximum Transmission
|
||||
|
@ -100,8 +87,9 @@ dns_servers:
|
|||
- 2606:4700:4700::1111
|
||||
- 2606:4700:4700::1001
|
||||
|
||||
# IP address for the local dns resolver
|
||||
local_service_ip: 172.16.0.1
|
||||
# Randomly generated IP address for the local dns resolver
|
||||
local_service_ip: "{{ '172.16.0.1' | ipmath(1048573 | random(seed=algo_server_name + ansible_fqdn)) }}"
|
||||
local_service_ipv6: "{{ 'fd00::1' | ipmath(1048573 | random(seed=algo_server_name + ansible_fqdn)) }}"
|
||||
|
||||
# Your Algo server will automatically install security updates. Some updates
|
||||
# require a reboot to take effect but your Algo server will not reboot itself
|
||||
|
@ -122,11 +110,11 @@ congrats:
|
|||
"# Config files and certificates are in the ./configs/ directory. #"
|
||||
"# Go to https://whoer.net/ after connecting #"
|
||||
"# and ensure that all your traffic passes through the VPN. #"
|
||||
"# Local DNS resolver {{ local_service_ip }} #"
|
||||
"# Local DNS resolver {{ local_service_ip }}{{ ', ' + local_service_ipv6 if ipv6_support else '' }} #"
|
||||
p12_pass: |
|
||||
"# The p12 and SSH keys password for new users is {{ p12_export_password }} #"
|
||||
ca_key_pass: |
|
||||
"# The CA key password is {{ CA_password }} #"
|
||||
"# The CA key password is {{ CA_password|default(omit) }} #"
|
||||
ssh_access: |
|
||||
"# Shell access: ssh -i {{ ansible_ssh_private_key_file|default(omit) }} {{ ansible_ssh_user|default(omit) }}@{{ ansible_ssh_host|default(omit) }} #"
|
||||
|
||||
|
@ -138,25 +126,24 @@ SSH_keys:
|
|||
cloud_providers:
|
||||
azure:
|
||||
size: Basic_A0
|
||||
image: 18.04-LTS
|
||||
image: 19.04
|
||||
digitalocean:
|
||||
size: s-1vcpu-1gb
|
||||
image: "ubuntu-18-04-x64"
|
||||
# Change the encrypted flag to "true" to enable AWS volume encryption, for encryption of data at rest.
|
||||
# Warning: the Algo script will take approximately 6 minutes longer to complete.
|
||||
# Also note that the documented AWS minimum permissions aren't sufficient.
|
||||
# You will have to edit the AWS user policy documented at
|
||||
# https://github.com/trailofbits/algo/blob/master/docs/cloud-amazon-ec2.md to also allow "ec2:CopyImage".
|
||||
# See https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_manage-edit.html
|
||||
image: "ubuntu-19-04-x64"
|
||||
ec2:
|
||||
# Change the encrypted flag to "true" to enable AWS volume encryption, for encryption of data at rest.
|
||||
# Warning: the Algo script will take approximately 6 minutes longer to complete.
|
||||
encrypted: false
|
||||
# Set use_existing_eip to "true" if you want to use a pre-allocated Elastic IP
|
||||
# Additional prompt will be raised to determine which IP to use
|
||||
use_existing_eip: false
|
||||
size: t2.micro
|
||||
image:
|
||||
name: "ubuntu-bionic-18.04"
|
||||
name: "ubuntu-disco-19.04"
|
||||
owner: "099720109477"
|
||||
gce:
|
||||
size: f1-micro
|
||||
image: ubuntu-1804
|
||||
image: ubuntu-1904
|
||||
external_static_ip: false
|
||||
lightsail:
|
||||
size: nano_1_0
|
||||
|
@ -169,7 +156,7 @@ cloud_providers:
|
|||
flavor_ram: ">=512"
|
||||
image: Ubuntu-18.04
|
||||
vultr:
|
||||
os: Ubuntu 18.04 x64
|
||||
os: Ubuntu 19.04 x64
|
||||
size: 1024 MB RAM,25 GB SSD,1.00 TB BW
|
||||
local:
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
# Using Ubuntu Server as a Client with WireGuard
|
||||
# Using Ubuntu as a Client with WireGuard
|
||||
|
||||
## Install WireGuard
|
||||
|
||||
To connect to your AlgoVPN using [WireGuard](https://www.wireguard.com) from Ubuntu Server, first install WireGuard:
|
||||
To connect to your AlgoVPN using [WireGuard](https://www.wireguard.com) from Ubuntu, 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 or later):
|
||||
sudo apt update
|
||||
# Update the list of available packages (not necessary on 18.04 or later):
|
||||
sudo apt update
|
||||
|
||||
# Install the tools and kernel module:
|
||||
sudo apt install wireguard
|
||||
sudo apt install wireguard openresolv
|
||||
```
|
||||
|
||||
For installation on other Linux distributions, see the [Installation](https://www.wireguard.com/install/) page on the WireGuard site.
|
||||
|
@ -21,28 +21,6 @@ For installation on other Linux distributions, see the [Installation](https://ww
|
|||
|
||||
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.
|
||||
|
||||
## 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:
|
||||
|
|
|
@ -89,26 +89,28 @@ Name the vpn server:
|
|||
After entering the server name, the script ask which region you wish to setup your new Algo instance in. Enter the number next to name of the region.
|
||||
|
||||
```
|
||||
What region should the server be located in?
|
||||
1. us-east-1 US East (N. Virginia)
|
||||
2. us-east-2 US East (Ohio)
|
||||
3. us-west-1 US West (N. California)
|
||||
4. us-west-2 US West (Oregon)
|
||||
5. ca-central-1 Canada (Central)
|
||||
6. eu-central-1 EU (Frankfurt)
|
||||
7. eu-west-1 EU (Ireland)
|
||||
8. eu-west-2 EU (London)
|
||||
9. eu-west-3 EU (Paris)
|
||||
10. ap-northeast-1 Asia Pacific (Tokyo)
|
||||
11. ap-northeast-2 Asia Pacific (Seoul)
|
||||
12. ap-northeast-3 Asia Pacific (Osaka-Local)
|
||||
13. ap-southeast-1 Asia Pacific (Singapore)
|
||||
14. ap-southeast-2 Asia Pacific (Sydney)
|
||||
15. ap-south-1 Asia Pacific (Mumbai)
|
||||
16. sa-east-1 South America (São Paulo)
|
||||
|
||||
Enter the number of your desired region:
|
||||
[1]: 10
|
||||
What region should the server be located in?
|
||||
(https://docs.aws.amazon.com/general/latest/gr/rande.html#ec2_region)
|
||||
1. ap-northeast-1
|
||||
2. ap-northeast-2
|
||||
3. ap-south-1
|
||||
4. ap-southeast-1
|
||||
5. ap-southeast-2
|
||||
6. ca-central-1
|
||||
7. eu-central-1
|
||||
8. eu-north-1
|
||||
9. eu-west-1
|
||||
10. eu-west-2
|
||||
11. eu-west-3
|
||||
12. sa-east-1
|
||||
13. us-east-1
|
||||
14. us-east-2
|
||||
15. us-west-1
|
||||
16. us-west-2
|
||||
|
||||
Enter the number of your desired region
|
||||
[13]
|
||||
:
|
||||
```
|
||||
|
||||
You will then be asked the remainder of the standard Algo setup questions.
|
||||
|
|
|
@ -34,8 +34,8 @@ What provider would you like to use?
|
|||
6. Google Compute Engine
|
||||
7. Scaleway
|
||||
8. OpenStack (DreamCompute optimised)
|
||||
9. Install to existing Ubuntu 18.04 server (Advanced)
|
||||
|
||||
9. Install to existing Ubuntu server (Advanced)
|
||||
|
||||
Enter the number of your desired provider
|
||||
:
|
||||
1
|
||||
|
@ -68,7 +68,7 @@ What region should the server be located in?
|
|||
7. sfo2 San Francisco 2
|
||||
8. sgp1 Singapore 1
|
||||
9. tor1 Toronto 1
|
||||
|
||||
|
||||
Enter the number of your desired region
|
||||
[6]
|
||||
:
|
||||
|
|
9
docs/cloud-scaleway.md
Normal file
9
docs/cloud-scaleway.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
### Configuration file
|
||||
|
||||
Algo requires an API key from your Scaleway account to create a server.
|
||||
The API key is generated by going to your Scaleway credentials at [https://console.scaleway.com/account/credentials](https://console.scaleway.com/account/credentials), and then selecting "Generate new token" on the right side of the box labeled "API Tokens".
|
||||
|
||||
Enter this token when Algo prompts you for the `auth token`.
|
||||
This information will be pass as the `algo_scaleway_token` variable when asked for in the Algo prompt.
|
||||
|
||||
Your organization ID is also on this page: https://console.scaleway.com/account/credentials
|
|
@ -1,10 +1,10 @@
|
|||
# Scripted Deployment
|
||||
# Deployment from Ansible
|
||||
|
||||
Before you begin, make sure you have installed all the dependencies necessary for your operating system as described in the [README](../README.md).
|
||||
|
||||
You can deploy Algo non-interactively by running the Ansible playbooks directly with `ansible-playbook`.
|
||||
|
||||
`ansible-playbook` accepts "tags" via the `-t` or `TAGS` options. You can pass tags as a list of comma separated values. Ansible will only run plays (install roles) with the specified tags.
|
||||
`ansible-playbook` accepts "tags" via the `-t` or `TAGS` options. You can pass tags as a list of comma separated values. Ansible will only run plays (install roles) with the specified tags. You can also use the `--skip-tags` option to skip certain parts of the install, such as `iptables` (overwrite iptables rules), `ipsec` (install strongSwan), `wireguard` (install Wireguard).
|
||||
|
||||
`ansible-playbook` accepts variables via the `-e` or `--extra-vars` option. You can pass variables as space separated key=value pairs. Algo requires certain variables that are listed below.
|
||||
|
||||
|
@ -23,25 +23,25 @@ ansible-playbook main.yml -e "provider=digitalocean
|
|||
do_token=token"
|
||||
```
|
||||
|
||||
See below for more information about providers and extra variables
|
||||
See below for more information about variables and roles.
|
||||
|
||||
### Variables
|
||||
|
||||
- `provider` - (Required) The provider to use. See possible values below
|
||||
- `server_name` - (Required) Server name. Default: algo
|
||||
- `ondemand_cellular` (Optional) VPN On Demand when connected to cellular networks. Default: false
|
||||
- `ondemand_wifi` - (Optional. See `ondemand_wifi_exclude`) VPN On Demand when connected to WiFi networks. Default: false
|
||||
- `ondemand_cellular` (Optional) VPN On Demand when connected to cellular networks with IPsec. Default: false
|
||||
- `ondemand_wifi` - (Optional. See `ondemand_wifi_exclude`) VPN On Demand when connected to WiFi networks with IPsec. Default: false
|
||||
- `ondemand_wifi_exclude` (Required if `ondemand_wifi` set) - WiFi networks to exclude from using the VPN. Comma-separated values
|
||||
- `local_dns` - (Optional) Enable a DNS resolver. Default: false
|
||||
- `ssh_tunneling` - (Optional) Enable SSH tunneling for each user. Default: false
|
||||
- `windows` - (Optional) Enables compatible ciphers and key exchange to support Windows clients, less secure. Default: false
|
||||
- `store_cakey` - (Optional) Whether or not keep the CA key (required to add users in the future, but less secure). Default: false
|
||||
|
||||
If any of those unspecified ansible will ask the user to input
|
||||
If any of the above variables are unspecified, ansible will ask the user to input them.
|
||||
|
||||
### Ansible roles
|
||||
|
||||
Roles can be activated by specifying an extra variable `provider`
|
||||
Cloud roles can be activated by specifying an extra variable `provider`.
|
||||
|
||||
Cloud roles:
|
||||
|
||||
|
@ -55,13 +55,25 @@ Cloud roles:
|
|||
|
||||
Server roles:
|
||||
|
||||
- role: vpn
|
||||
- role: strongswan
|
||||
* Installs [strongSwan](https://www.strongswan.org/)
|
||||
* Enables AppArmor, limits CPU and memory access, and drops user privileges
|
||||
* Builds a Certificate Authority (CA) with [easy-rsa-ipsec](https://github.com/ValdikSS/easy-rsa-ipsec) and creates one client certificate per user
|
||||
* Bundles the appropriate certificates into Apple mobileconfig profiles and Powershell scripts for each user
|
||||
- role: dns_adblocking
|
||||
* Installs the [dnsmasq](http://www.thekelleys.org.uk/dnsmasq/doc.html) local resolver with a blacklist for advertising domains
|
||||
* Constrains dnsmasq with AppArmor and cgroups CPU and memory limitations
|
||||
- role: dns_encryption
|
||||
* Installs [dnscrypt-proxy](https://github.com/jedisct1/dnscrypt-proxy)
|
||||
* Constrains dnscrypt-proxy with AppArmor and cgroups CPU and memory limitations
|
||||
- role: ssh_tunneling
|
||||
* Adds a restricted `algo` group with no shell access and limited SSH forwarding options
|
||||
* Creates one limited, local account and an SSH public key for each user
|
||||
- role: wireguard
|
||||
* Installs a [Wireguard](https://www.wireguard.com/) server, with a startup script, and automatic checks for upgrades
|
||||
* Creates wireguard.conf files for Linux clients as well as QR codes for Apple/Android clients
|
||||
|
||||
Note: The `vpn` role generates Apple profiles with On-Demand Wifi and Cellular if you pass the following variables:
|
||||
Note: The `strongswan` role generates Apple profiles with On-Demand Wifi and Cellular if you pass the following variables:
|
||||
|
||||
- ondemand_wifi: true
|
||||
- ondemand_wifi_exclude: HomeNet,OfficeWifi
|
||||
|
@ -91,9 +103,9 @@ Possible options can be gathered calling to https://api.digitalocean.com/v2/regi
|
|||
|
||||
Required variables:
|
||||
|
||||
- aws_access_key
|
||||
- aws_access_key: `AKIA...`
|
||||
- aws_secret_key
|
||||
- region
|
||||
- region: e.g. `us-east-1`
|
||||
|
||||
Possible options can be gathered via cli `aws ec2 describe-regions`
|
||||
|
||||
|
@ -114,7 +126,8 @@ Additional variables:
|
|||
"ec2:DescribeImages",
|
||||
"ec2:DescribeKeyPairs",
|
||||
"ec2:DescribeRegions",
|
||||
"ec2:ImportKeyPair"
|
||||
"ec2:ImportKeyPair",
|
||||
"ec2:CopyImage"
|
||||
],
|
||||
"Resource": [
|
||||
"*"
|
||||
|
@ -179,8 +192,8 @@ Required variables:
|
|||
|
||||
Required variables:
|
||||
|
||||
- [vultr_config](https://trailofbits.github.io/algo/cloud-vultr.html)
|
||||
- [region](https://api.vultr.com/v1/regions/list)
|
||||
- [vultr_config](https://trailofbits.github.io/algo/cloud-vultr.html): /path/to/.vultr.ini
|
||||
- [region](https://api.vultr.com/v1/regions/list): e.g. `Chicago`, `'New Jersey'`
|
||||
|
||||
### Azure
|
||||
|
||||
|
@ -196,9 +209,9 @@ Required variables:
|
|||
|
||||
Required variables:
|
||||
|
||||
- aws_access_key
|
||||
- aws_access_key: `AKIA...`
|
||||
- aws_secret_key
|
||||
- region
|
||||
- region: e.g. `us-east-1`
|
||||
|
||||
Possible options can be gathered via cli `aws lightsail get-regions`
|
||||
|
||||
|
@ -230,13 +243,7 @@ Possible options can be gathered via cli `aws lightsail get-regions`
|
|||
Required variables:
|
||||
|
||||
- [scaleway_token](https://www.scaleway.com/docs/generate-an-api-token/)
|
||||
- [scaleway_org](https://cloud.scaleway.com/#/billing)
|
||||
- region
|
||||
|
||||
Possible regions:
|
||||
|
||||
- ams1
|
||||
- par1
|
||||
- region: e.g. ams1, par1
|
||||
|
||||
### OpenStack
|
||||
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
# Deploy from script or cloud-init
|
||||
|
||||
You can use `install.sh` to prepare the environment and deploy AlgoVPN on the local Ubuntu server in one shot using cloud-init or run the script directly on the server. The script doesn't configure any parameters in your cloud, so it's on your own to configure related [firewall rules](/docs/firewalls.md), a floating ip address and other resources you may need.
|
||||
You can use `install.sh` to prepare the environment and deploy AlgoVPN on the local Ubuntu server in one shot using cloud-init, or run the script directly on the server after it's been created. The script doesn't configure any parameters in your cloud, so it's on your own to configure related [firewall rules](/docs/firewalls.md), a floating ip address and other resources you may need. The output of the install script (including the p12 and CA passwords) and user config files will be installed into the `/opt/algo` directory.
|
||||
|
||||
## Cloud init deployment
|
||||
|
||||
You can copy-paste the snippet below to the user data (cloud-init or startup script) field when creating a new server. For now it is only possible for [DigitalOcean](https://www.digitalocean.com/docs/droplets/resources/metadata/), Amazon [EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html) and [Lightsail](https://lightsail.aws.amazon.com/ls/docs/en/articles/lightsail-how-to-configure-server-additional-data-shell-script), [Google Cloud](https://cloud.google.com/compute/docs/startupscript) and [Azure](https://docs.microsoft.com/en-us/azure/virtual-machines/linux/using-cloud-init).
|
||||
You can copy-paste the snippet below to the user data (cloud-init or startup script) field when creating a new server. For now it is only possible for [DigitalOcean](https://www.digitalocean.com/docs/droplets/resources/metadata/), Amazon [EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html) and [Lightsail](https://lightsail.aws.amazon.com/ls/docs/en/articles/lightsail-how-to-configure-server-additional-data-shell-script), [Google Cloud](https://cloud.google.com/compute/docs/startupscript), [Azure](https://docs.microsoft.com/en-us/azure/virtual-machines/linux/using-cloud-init) and [Vultr](https://my.vultr.com/startup/), although Vultr doesn't [officially support cloud-init](https://www.vultr.com/docs/getting-started-with-cloud-init).
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
curl -s https://raw.githubusercontent.com/trailofbits/algo/master/install.sh | sudo -E bash -x
|
||||
```
|
||||
The command will prepare the environment and install AlgoVPN with default parameters. If you want to modify the behaviour you may define additional variables.
|
||||
The command will prepare the environment and install AlgoVPN with the default parameters below. If you want to modify the behavior you may define additional variables.
|
||||
|
||||
## Variables
|
||||
|
||||
`METHOD` - which method of the deployment to use. Possible values are local and cloud. Default: cloud. The cloud method is intended to use in cloud-init deployments only. If you are not using cloud-init to deploy the server you have to use the local method
|
||||
`ONDEMAND_CELLULAR` - "Connect On Demand" when connected to cellular networks. Bollean. Default: false
|
||||
`ONDEMAND_WIFI` - "Connect On Demand" when connected to Wi-Fi. Default: false
|
||||
`ONDEMAND_WIFI_EXCLUDE` - List the names of any trusted Wi-Fi networks where macOS/iOS IPsec clients should not use "Connect On Demand". Comma-separated list.
|
||||
`WINDOWS` - To support Windows 10 or Linux Desktop clients. Default: false
|
||||
`STORE_CAKEY` - To retain the CA key. (required to add users in the future, but less secure). Default: false.
|
||||
`LOCAL_DNS` - To install an ad blocking DNS resolver. Default: false.
|
||||
`SSH_TUNNELING` - Enable SSH tunneling for each user. Default: false
|
||||
`ENDPOINT` - The public IP address or domain name of your server: (IMPORTANT! This is used to verify the certificate). It will be gathered automatically for DigitalOcean, AWS, GCE or Azure if the `METHOD` is cloud. Otherwise you need to define this variable according to your public IP address.
|
||||
`USERS` - list of VPN users. Comma-separated list.
|
||||
`METHOD` - which method of the deployment to use. Possible values are local and cloud. Default: cloud. The cloud method is intended to use in cloud-init deployments only. If you are not using cloud-init to deploy the server you have to use the local method.
|
||||
`ONDEMAND_CELLULAR` - "Connect On Demand" when connected to cellular networks. Boolean. Default: false.
|
||||
`ONDEMAND_WIFI` - "Connect On Demand" when connected to Wi-Fi. Default: false.
|
||||
`ONDEMAND_WIFI_EXCLUDE` - List the names of any trusted Wi-Fi networks where macOS/iOS IPsec clients should not use "Connect On Demand". Comma-separated list.
|
||||
`WINDOWS` - To support Windows 10 or Linux Desktop clients. Default: false.
|
||||
`STORE_CAKEY` - To retain the CA key. (required to add users in the future, but less secure). Default: false.
|
||||
`LOCAL_DNS` - To install an ad blocking DNS resolver. Default: false.
|
||||
`SSH_TUNNELING` - Enable SSH tunneling for each user. Default: false.
|
||||
`ENDPOINT` - The public IP address or domain name of your server: (IMPORTANT! This is used to verify the certificate). It will be gathered automatically for DigitalOcean, AWS, GCE, Azure or Vultr if the `METHOD` is cloud. Otherwise you need to define this variable according to your public IP address.
|
||||
`USERS` - list of VPN users. Comma-separated list. Default: user1.
|
||||
`REPO_SLUG` - Owner and repository that used to get the installation scripts from. Default: trailofbits/algo.
|
||||
`REPO_BRANCH` - Branch for `REPO_SLUG`. Default: master.
|
||||
`EXTRA_VARS` - Additional extra variables.
|
||||
`ANSIBLE_EXTRA_ARGS` - Any available ansible parameters. ie: `--skip-tags apparmor`.
|
||||
`REPO_BRANCH` - Branch for `REPO_SLUG`. Default: master.
|
||||
`EXTRA_VARS` - Additional extra variables.
|
||||
`ANSIBLE_EXTRA_ARGS` - Any available ansible parameters. ie: `--skip-tags apparmor`.
|
||||
|
||||
## Examples
|
||||
|
||||
|
@ -46,6 +46,7 @@ curl -s https://raw.githubusercontent.com/trailofbits/algo/master/install.sh | s
|
|||
```
|
||||
export METHOD=local
|
||||
export ONDEMAND_CELLULAR=true
|
||||
export ENDPOINT=[your server's IP here]
|
||||
curl -s https://raw.githubusercontent.com/trailofbits/algo/master/install.sh | sudo -E bash -x
|
||||
```
|
||||
|
||||
|
@ -54,5 +55,5 @@ curl -s https://raw.githubusercontent.com/trailofbits/algo/master/install.sh | s
|
|||
The arguments order as per [variables](#variables) above
|
||||
|
||||
```
|
||||
curl -s https://raw.githubusercontent.com/trailofbits/algo/master/install.sh | sudo -E bash -x -s local true false _null true true true true myvpnserver.com
|
||||
curl -s https://raw.githubusercontent.com/trailofbits/algo/master/install.sh | sudo -E bash -x -s local true false _null true true true true myvpnserver.com phone,laptop,desktop
|
||||
```
|
||||
|
|
|
@ -4,7 +4,7 @@ You can use Algo to configure a local server as an AlgoVPN rather than create an
|
|||
|
||||
Install the Algo scripts on your server and follow the normal installation instructions, then choose:
|
||||
```
|
||||
Install to existing Ubuntu 18.04 server (Advanced)
|
||||
Install to existing Ubuntu 18.04 or 19.04 server (Advanced)
|
||||
```
|
||||
Make sure your server is running the operating system specified.
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Algo officially supports DigitalOcean, Amazon Web Services, Microsoft Azure, and Google Cloud Engine. If you want to deploy Algo on another virtual hosting provider, that provider must support:
|
||||
|
||||
1. the base operating system image that Algo uses (Ubuntu 18.04), and
|
||||
1. the base operating system image that Algo uses (Ubuntu 18.04, 19.04), and
|
||||
2. a minimum of certain kernel modules required for the strongSwan IPsec server.
|
||||
|
||||
Please see the [Required Kernel Modules](https://wiki.strongswan.org/projects/strongswan/wiki/KernelModules) documentation from strongSwan for a list of the specific required modules and a script to check for them. As a first step, we recommend running their shell script to determine initial compatibility with your new hosting provider.
|
||||
|
|
|
@ -50,7 +50,7 @@ Algo is short for "Al Gore", the **V**ice **P**resident of **N**etworks everywhe
|
|||
|
||||
## Can DNS filtering be disabled?
|
||||
|
||||
You can temporarily disable DNS filtering for all IPsec clients at once with the following workaround: SSH to your Algo server (using the 'shell access' command printed upon a successful deployment), edit `/etc/ipsec.conf`, and change `rightdns=172.16.0.1` to `rightdns=8.8.8.8`. Then run `sudo systemctl restart strongswan`. DNS filtering for Wireguard clients has to be disabled on each client device separately by modifying the settings in the app, or by directly modifying the `DNS` setting on the `clientname.conf` file. If all else fails, we recommend deploying a new Algo server without the adblocking feature enabled.
|
||||
You can temporarily disable DNS filtering for all IPsec clients at once with the following workaround: SSH to your Algo server (using the 'shell access' command printed upon a successful deployment), edit `/etc/ipsec.conf`, and change `rightdns=<random_ip>` to `rightdns=8.8.8.8`. Then run `sudo systemctl restart strongswan`. DNS filtering for Wireguard clients has to be disabled on each client device separately by modifying the settings in the app, or by directly modifying the `DNS` setting on the `clientname.conf` file. If all else fails, we recommend deploying a new Algo server without the adblocking feature enabled.
|
||||
|
||||
## Wasn't IPSEC backdoored by the US government?
|
||||
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 75 KiB |
|
@ -1,21 +1,29 @@
|
|||
# Algo VPN documentation
|
||||
|
||||
* Setup instructions
|
||||
- Documentation for available [Ansible roles](setup-roles.md)
|
||||
* Deployment instructions
|
||||
- Deploy from [Fedora Workstation (26)](deploy-from-fedora-workstation.md)
|
||||
- Deploy from [RedHat/CentOS 6.x](deploy-from-redhat-centos6.md)
|
||||
- Deploy from [Windows](deploy-from-windows.md)
|
||||
- Deploy from [Ansible](deploy-from-ansible.md) directly
|
||||
- Deploy from a [Docker container](deploy-from-docker.md)
|
||||
- Deploy from [Ansible](deploy-from-ansible.md) non-interactively
|
||||
- Deploy onto a [cloud server at time of creation](deploy-from-script-or-cloud-init-to-localhost.md)
|
||||
* Client setup
|
||||
- Setup [Android](client-android.md) clients
|
||||
- Setup [Generic/Linux](client-linux.md) clients with Ansible
|
||||
* Cloud setup
|
||||
- Setup Ubuntu clients to use [WireGuard](client-linux-wireguard.md)
|
||||
- Setup Apple devices to use [IPSEC](client-apple-ipsec.md)
|
||||
- Setup Macs running macOS 10.13 or older to use [Wireguard](client-macos-wireguard.md)
|
||||
- Manual Windows 10 client setup for [IPSEC](client-windows.md)
|
||||
* Cloud provider setup
|
||||
- Configure [Amazon EC2](cloud-amazon-ec2.md)
|
||||
- Configure [Azure](cloud-azure.md)
|
||||
- Configure [DigitalOcean](cloud-do.md)
|
||||
- Configure [Google Cloud Platform](cloud-gce.md)
|
||||
- Configure [Vultr](cloud-vultr.md)
|
||||
* Advanced Deployment
|
||||
- Deploy to your own [FreeBSD](deploy-to-freebsd.md) server
|
||||
- Deploy to your own [Ubuntu 18.04](deploy-to-ubuntu.md) server
|
||||
- Deploy to your own [Ubuntu](deploy-to-ubuntu.md) server
|
||||
- Deploy to an [unsupported cloud provider](deploy-to-unsupported-cloud.md)
|
||||
* [FAQ](faq.md)
|
||||
* [Firewalls](firewalls.md)
|
||||
* [Troubleshooting](troubleshooting.md)
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
# Ansible Roles
|
||||
|
||||
## Required roles
|
||||
|
||||
* **Common**
|
||||
* Installs several required packages and software updates, then reboots if necessary
|
||||
* Configures network interfaces, and enables packet forwarding on them
|
||||
* **VPN**
|
||||
* Installs [strongSwan](https://www.strongswan.org/), enables AppArmor, limits CPU and memory access, and drops user privileges
|
||||
* Builds a Certificate Authority (CA) with [easy-rsa-ipsec](https://github.com/ValdikSS/easy-rsa-ipsec) and creates one client certificate per user
|
||||
* Bundles the appropriate certificates into Apple mobileconfig profiles for each user
|
||||
* Configures IPtables to block traffic that might pose a risk to VPN users, such as [SMB/CIFS](https://medium.com/@ValdikSS/deanonymizing-windows-users-and-capturing-microsoft-and-vpn-accounts-f7e53fe73834)
|
||||
|
||||
## Optional roles
|
||||
|
||||
* **Security Enhancements**
|
||||
* Enables [unattended-upgrades](https://help.ubuntu.com/community/AutomaticSecurityUpdates) to ensure available patches are always applied
|
||||
* Modify features like core dumps, kernel parameters, and SUID binaries to limit possible attacks
|
||||
* Enhances SSH with modern ciphers and seccomp, and restricts access to old or unwanted features like X11 forwarding and SFTP
|
||||
* **DNS-based Adblocking**
|
||||
* Install the [dnsmasq](http://www.thekelleys.org.uk/dnsmasq/doc.html) local resolver with a blacklist for advertising domains
|
||||
* Constrains dnsmasq with AppArmor and cgroups CPU and memory limitations
|
||||
* **DNS encryption**
|
||||
* Install [dnscrypt-proxy](https://github.com/jedisct1/dnscrypt-proxy)
|
||||
* Constrains dingo with AppArmor and cgroups CPU and memory limitations
|
||||
* **SSH Tunneling**
|
||||
* Adds a restricted `algo` group with no shell access and limited SSH forwarding options
|
||||
* Creates one limited, local account per user and an SSH public key for each
|
|
@ -18,7 +18,7 @@ First of all, check [this](https://github.com/trailofbits/algo#features) and ens
|
|||
* [Windows: The value of parameter linuxConfiguration.ssh.publicKeys.keyData is invalid](#windows-the-value-of-parameter-linuxconfigurationsshpublickeyskeydata-is-invalid)
|
||||
* [Docker: Failed to connect to the host via ssh](#docker-failed-to-connect-to-the-host-via-ssh)
|
||||
* [Wireguard: Unable to find 'configs/...' in expected paths](#wireguard-unable-to-find-configs-in-expected-paths)
|
||||
* [Ubuntu Error: "unable to write 'random state" when generating CA password](#ubuntu-error-unable-to-write-random-state-when-generating-ca-password")
|
||||
* [Ubuntu Error: "unable to write 'random state'" when generating CA password](#ubuntu-error-unable-to-write-random-state-when-generating-ca-password)
|
||||
* [Connection Problems](#connection-problems)
|
||||
* [I'm blocked or get CAPTCHAs when I access certain websites](#im-blocked-or-get-captchas-when-i-access-certain-websites)
|
||||
* [I want to change the list of trusted Wifi networks on my Apple device](#i-want-to-change-the-list-of-trusted-wifi-networks-on-my-apple-device)
|
||||
|
@ -28,6 +28,7 @@ First of all, check [this](https://github.com/trailofbits/algo#features) and ens
|
|||
* [I can't get Network Manager to connect to the Algo server](#i-cant-get-network-manager-to-connect-to-the-algo-server)
|
||||
* [Various websites appear to be offline through the VPN](#various-websites-appear-to-be-offline-through-the-vpn)
|
||||
* [Clients appear stuck in a reconnection loop](#clients-appear-stuck-in-a-reconnection-loop)
|
||||
* [Wireguard: clients can connect on Wifi but not LTE](#wireguard-clients-can-connect-on-wifi-but-not-lte)
|
||||
* ["Error 809" or IKE_AUTH requests that never make it to the server](#error-809-or-ike_auth-requests-that-never-make-it-to-the-server)
|
||||
* [Windows: Parameter is incorrect](#windows-parameter-is-incorrect)
|
||||
* [I have a problem not covered here](#i-have-a-problem-not-covered-here)
|
||||
|
@ -153,7 +154,9 @@ You need to reset the permissions on your `.ssh` directory. Run `chmod 700 /home
|
|||
|
||||
### The region you want is not available
|
||||
|
||||
You want to install Algo to a specific region in a cloud provider, but that region is not available in the list given by the installer. In that case, you should [file an issue](https://github.com/trailofbits/algo/issues/new). Cloud providers add new regions on a regular basis and we don't always keep up. File an issue and give us information about what region is missing and we'll add it.
|
||||
Algo downloads the regions from the supported cloud providers (other than Microsoft Azure) listed in the first menu using APIs. If the region you want isn't available, the cloud provider has probably taken it offline for some reason. You should investigate further with your cloud provider.
|
||||
|
||||
If there's a specific region you want to install to in Microsoft Azure that isn't available, you should [file an issue](https://github.com/trailofbits/algo/issues/new), give us information about what region is missing, and we'll add it.
|
||||
|
||||
### AWS: SSH permission denied with an ECDSA key
|
||||
|
||||
|
@ -269,7 +272,7 @@ sudo rm -rf /etc/wireguard/*.lock
|
|||
```
|
||||
Then immediately re-run `./algo`.
|
||||
|
||||
### Ubuntu Error: "unable to write 'random state" when generating CA password
|
||||
### Ubuntu Error: "unable to write 'random state'" when generating CA password
|
||||
|
||||
When running Algo, you received an error like this:
|
||||
|
||||
|
@ -406,6 +409,12 @@ Example command:
|
|||
sed -i -e 's/#*.dos_protection = yes/dos_protection = no/' /etc/strongswan.d/charon.conf && ipsec restart
|
||||
```
|
||||
|
||||
### WireGuard: Clients can connect on Wifi but not LTE
|
||||
|
||||
Certain cloud providers (like AWS Lightsail) don't assign an IPv6 address to your server, but certain cellular carriers (e.g. T-Mobile in the United States, [EE](https://community.ee.co.uk/t5/4G-and-mobile-data/IPv4-VPN-Connectivity/td-p/757881) in the United Kingdom) operate an IPv6-only network. This somehow leads to the Wireguard app not being able to make a connection when transitioning to cell service. Go to the Wireguard app on the device when you're having problems with cell connectivity and select "Export log file" or similar option. If you see a long string of error messages like "`Failed to send data packet write udp6 [::]:49727->[2607:7700:0:2a:0:1:354:40ae]:51820: sendto: no route to host` then you might be having this problem.
|
||||
|
||||
Manually disconnecting and then reconnecting should restore your connection. To solve this, you need to either "force IPv4 connection" if available on your phone, or install an IPv4 APN, which might be available from your carrier tech support. T-mobile's is available [for iOS here under "iOS IPv4/IPv6 fix"](https://www.reddit.com/r/tmobile/wiki/index), and [here is a walkthrough for Android phones](https://www.myopenrouter.com/article/vpn-connections-not-working-t-mobile-heres-how-fix).
|
||||
|
||||
### "Error 809" or IKE_AUTH requests that never make it to the server
|
||||
|
||||
On Windows, this issue may manifest with an error message that says "The network connection between your computer and the VPN server could not be established because the remote server is not responding... This is Error 809." On other operating systems, you may try to debug the issue by capturing packets with tcpdump and notice that, while IKE_SA_INIT request and responses are exchanged between the client and server, IKE_AUTH requests never make it to the server.
|
||||
|
|
20
input.yml
20
input.yml
|
@ -20,13 +20,13 @@
|
|||
- { name: Google Compute Engine, alias: gce }
|
||||
- { name: Scaleway, alias: scaleway}
|
||||
- { name: OpenStack (DreamCompute optimised), alias: openstack }
|
||||
- { name: Install to existing Ubuntu 18.04 server (Advanced), alias: local }
|
||||
- { name: Install to existing Ubuntu 18.04 or 19.04 server (Advanced), alias: local }
|
||||
vars_files:
|
||||
- config.cfg
|
||||
|
||||
tasks:
|
||||
- block:
|
||||
- name: Region prompt
|
||||
- name: Cloud prompt
|
||||
pause:
|
||||
prompt: |
|
||||
What provider would you like to use?
|
||||
|
@ -122,11 +122,11 @@
|
|||
{{ _server | regex_replace('(?!\.)(\W|_)', '-') }}
|
||||
algo_ondemand_cellular: >-
|
||||
{% if ondemand_cellular is defined %}{{ ondemand_cellular | bool }}
|
||||
{%- elif _ondemand_cellular.user_input %}{{ booleans_map[_ondemand_cellular.user_input] | default(defaults['ondemand_cellular']) }}
|
||||
{%- elif _ondemand_cellular.user_input is defined %}{{ 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 %}{{ booleans_map[_ondemand_wifi.user_input] | default(defaults['ondemand_wifi']) }}
|
||||
{%- elif _ondemand_wifi.user_input is defined %}{{ 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 }}
|
||||
|
@ -135,19 +135,19 @@
|
|||
{%- else %}{{ '_null' | b64encode }}{% endif %}
|
||||
algo_local_dns: >-
|
||||
{% if local_dns is defined %}{{ local_dns | bool }}
|
||||
{%- elif _local_dns.user_input %}{{ booleans_map[_local_dns.user_input] | default(defaults['local_dns']) }}
|
||||
{%- elif _local_dns.user_input is defined %}{{ 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 %}{{ booleans_map[_ssh_tunneling.user_input] | default(defaults['ssh_tunneling']) }}
|
||||
{%- elif _ssh_tunneling.user_input is defined %}{{ 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 %}{{ booleans_map[_windows.user_input] | default(defaults['windows']) }}
|
||||
{%- elif _windows.user_input is defined %}{{ 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 %}{{ booleans_map[_store_cakey.user_input] | default(defaults['store_cakey']) }}
|
||||
{%- else %}false{% endif %}
|
||||
{% if ipsec_enabled %}{%- if store_cakey is defined %}{{ store_cakey | bool }}
|
||||
{%- elif _store_cakey.user_input is defined %}{{ booleans_map[_store_cakey.user_input] | default(defaults['store_cakey']) }}
|
||||
{%- else %}false{% endif %}{% endif %}
|
||||
rescue:
|
||||
- include_tasks: playbooks/rescue.yml
|
||||
|
|
619
library/scaleway_compute.py
Normal file
619
library/scaleway_compute.py
Normal file
|
@ -0,0 +1,619 @@
|
|||
#!/usr/bin/python
|
||||
#
|
||||
# Scaleway Compute management module
|
||||
#
|
||||
# Copyright (C) 2018 Online SAS.
|
||||
# https://www.scaleway.com
|
||||
#
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {
|
||||
'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'
|
||||
}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: scaleway_compute
|
||||
short_description: Scaleway compute management module
|
||||
version_added: "2.6"
|
||||
author: Remy Leone (@sieben)
|
||||
description:
|
||||
- "This module manages compute instances on Scaleway."
|
||||
extends_documentation_fragment: scaleway
|
||||
|
||||
options:
|
||||
|
||||
enable_ipv6:
|
||||
description:
|
||||
- Enable public IPv6 connectivity on the instance
|
||||
default: false
|
||||
type: bool
|
||||
|
||||
boot_type:
|
||||
description:
|
||||
- Boot method
|
||||
default: bootscript
|
||||
choices:
|
||||
- bootscript
|
||||
- local
|
||||
|
||||
image:
|
||||
description:
|
||||
- Image identifier used to start the instance with
|
||||
required: true
|
||||
|
||||
name:
|
||||
description:
|
||||
- Name of the instance
|
||||
|
||||
organization:
|
||||
description:
|
||||
- Organization identifier
|
||||
required: true
|
||||
|
||||
state:
|
||||
description:
|
||||
- Indicate desired state of the instance.
|
||||
default: present
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
- running
|
||||
- restarted
|
||||
- stopped
|
||||
|
||||
tags:
|
||||
description:
|
||||
- List of tags to apply to the instance (5 max)
|
||||
required: false
|
||||
default: []
|
||||
|
||||
region:
|
||||
description:
|
||||
- Scaleway compute zone
|
||||
required: true
|
||||
choices:
|
||||
- ams1
|
||||
- EMEA-NL-EVS
|
||||
- par1
|
||||
- EMEA-FR-PAR1
|
||||
|
||||
commercial_type:
|
||||
description:
|
||||
- Commercial name of the compute node
|
||||
required: true
|
||||
choices:
|
||||
- ARM64-2GB
|
||||
- ARM64-4GB
|
||||
- ARM64-8GB
|
||||
- ARM64-16GB
|
||||
- ARM64-32GB
|
||||
- ARM64-64GB
|
||||
- ARM64-128GB
|
||||
- C1
|
||||
- C2S
|
||||
- C2M
|
||||
- C2L
|
||||
- START1-XS
|
||||
- START1-S
|
||||
- START1-M
|
||||
- START1-L
|
||||
- X64-15GB
|
||||
- X64-30GB
|
||||
- X64-60GB
|
||||
- X64-120GB
|
||||
|
||||
wait:
|
||||
description:
|
||||
- Wait for the instance to reach its desired state before returning.
|
||||
type: bool
|
||||
default: 'no'
|
||||
|
||||
wait_timeout:
|
||||
description:
|
||||
- Time to wait for the server to reach the expected state
|
||||
required: false
|
||||
default: 300
|
||||
|
||||
wait_sleep_time:
|
||||
description:
|
||||
- Time to wait before every attempt to check the state of the server
|
||||
required: false
|
||||
default: 3
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: Create a server
|
||||
scaleway_compute:
|
||||
name: foobar
|
||||
state: present
|
||||
image: 89ee4018-f8c3-4dc4-a6b5-bca14f985ebe
|
||||
organization: 951df375-e094-4d26-97c1-ba548eeb9c42
|
||||
region: ams1
|
||||
commercial_type: VC1S
|
||||
tags:
|
||||
- test
|
||||
- www
|
||||
|
||||
- name: Destroy it right after
|
||||
scaleway_compute:
|
||||
name: foobar
|
||||
state: absent
|
||||
image: 89ee4018-f8c3-4dc4-a6b5-bca14f985ebe
|
||||
organization: 951df375-e094-4d26-97c1-ba548eeb9c42
|
||||
region: ams1
|
||||
commercial_type: VC1S
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
'''
|
||||
|
||||
import datetime
|
||||
import time
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.six.moves.urllib.parse import quote as urlquote
|
||||
from ansible.module_utils.scaleway import SCALEWAY_LOCATION, scaleway_argument_spec, Scaleway
|
||||
|
||||
SCALEWAY_COMMERCIAL_TYPES = [
|
||||
|
||||
# Virtual ARM64 compute instance
|
||||
'ARM64-2GB',
|
||||
'ARM64-4GB',
|
||||
'ARM64-8GB',
|
||||
'ARM64-16GB',
|
||||
'ARM64-32GB',
|
||||
'ARM64-64GB',
|
||||
'ARM64-128GB',
|
||||
|
||||
# Baremetal
|
||||
'C1', # ARM64 (4 cores) - 2GB
|
||||
'C2S', # X86-64 (4 cores) - 8GB
|
||||
'C2M', # X86-64 (8 cores) - 16GB
|
||||
'C2L', # x86-64 (8 cores) - 32 GB
|
||||
|
||||
# Virtual X86-64 compute instance
|
||||
'START1-XS', # Starter X86-64 (1 core) - 1GB - 25 GB NVMe
|
||||
'START1-S', # Starter X86-64 (2 cores) - 2GB - 50 GB NVMe
|
||||
'START1-M', # Starter X86-64 (4 cores) - 4GB - 100 GB NVMe
|
||||
'START1-L', # Starter X86-64 (8 cores) - 8GB - 200 GB NVMe
|
||||
'X64-15GB',
|
||||
'X64-30GB',
|
||||
'X64-60GB',
|
||||
'X64-120GB',
|
||||
]
|
||||
|
||||
SCALEWAY_SERVER_STATES = (
|
||||
'stopped',
|
||||
'stopping',
|
||||
'starting',
|
||||
'running',
|
||||
'locked'
|
||||
)
|
||||
|
||||
SCALEWAY_TRANSITIONS_STATES = (
|
||||
"stopping",
|
||||
"starting",
|
||||
"pending"
|
||||
)
|
||||
|
||||
|
||||
def fetch_state(compute_api, server):
|
||||
compute_api.module.debug("fetch_state of server: %s" % server["id"])
|
||||
response = compute_api.get(path="servers/%s" % server["id"])
|
||||
|
||||
if response.status_code == 404:
|
||||
return "absent"
|
||||
|
||||
if not response.ok:
|
||||
msg = 'Error during state fetching: (%s) %s' % (response.status_code, response.json)
|
||||
compute_api.module.fail_json(msg=msg)
|
||||
|
||||
try:
|
||||
compute_api.module.debug("Server %s in state: %s" % (server["id"], response.json["server"]["state"]))
|
||||
return response.json["server"]["state"]
|
||||
except KeyError:
|
||||
compute_api.module.fail_json(msg="Could not fetch state in %s" % response.json)
|
||||
|
||||
|
||||
def wait_to_complete_state_transition(compute_api, server):
|
||||
wait = compute_api.module.params["wait"]
|
||||
if not wait:
|
||||
return
|
||||
wait_timeout = compute_api.module.params["wait_timeout"]
|
||||
wait_sleep_time = compute_api.module.params["wait_sleep_time"]
|
||||
|
||||
start = datetime.datetime.utcnow()
|
||||
end = start + datetime.timedelta(seconds=wait_timeout)
|
||||
while datetime.datetime.utcnow() < end:
|
||||
compute_api.module.debug("We are going to wait for the server to finish its transition")
|
||||
if fetch_state(compute_api, server) not in SCALEWAY_TRANSITIONS_STATES:
|
||||
compute_api.module.debug("It seems that the server is not in transition anymore.")
|
||||
compute_api.module.debug("Server in state: %s" % fetch_state(compute_api, server))
|
||||
break
|
||||
time.sleep(wait_sleep_time)
|
||||
else:
|
||||
compute_api.module.fail_json(msg="Server takes too long to finish its transition")
|
||||
|
||||
|
||||
def create_server(compute_api, server):
|
||||
compute_api.module.debug("Starting a create_server")
|
||||
target_server = None
|
||||
response = compute_api.post(path="servers",
|
||||
data={"enable_ipv6": server["enable_ipv6"],
|
||||
"boot_type": server["boot_type"],
|
||||
"tags": server["tags"],
|
||||
"commercial_type": server["commercial_type"],
|
||||
"image": server["image"],
|
||||
"name": server["name"],
|
||||
"organization": server["organization"]})
|
||||
|
||||
if not response.ok:
|
||||
msg = 'Error during server creation: (%s) %s' % (response.status_code, response.json)
|
||||
compute_api.module.fail_json(msg=msg)
|
||||
|
||||
try:
|
||||
target_server = response.json["server"]
|
||||
except KeyError:
|
||||
compute_api.module.fail_json(msg="Error in getting the server information from: %s" % response.json)
|
||||
|
||||
wait_to_complete_state_transition(compute_api=compute_api, server=target_server)
|
||||
|
||||
return target_server
|
||||
|
||||
|
||||
def restart_server(compute_api, server):
|
||||
return perform_action(compute_api=compute_api, server=server, action="reboot")
|
||||
|
||||
|
||||
def stop_server(compute_api, server):
|
||||
return perform_action(compute_api=compute_api, server=server, action="poweroff")
|
||||
|
||||
|
||||
def start_server(compute_api, server):
|
||||
return perform_action(compute_api=compute_api, server=server, action="poweron")
|
||||
|
||||
|
||||
def perform_action(compute_api, server, action):
|
||||
response = compute_api.post(path="servers/%s/action" % server["id"],
|
||||
data={"action": action})
|
||||
if not response.ok:
|
||||
msg = 'Error during server %s: (%s) %s' % (action, response.status_code, response.json)
|
||||
compute_api.module.fail_json(msg=msg)
|
||||
|
||||
wait_to_complete_state_transition(compute_api=compute_api, server=server)
|
||||
|
||||
return response
|
||||
|
||||
|
||||
def remove_server(compute_api, server):
|
||||
compute_api.module.debug("Starting remove server strategy")
|
||||
response = compute_api.delete(path="servers/%s" % server["id"])
|
||||
if not response.ok:
|
||||
msg = 'Error during server deletion: (%s) %s' % (response.status_code, response.json)
|
||||
compute_api.module.fail_json(msg=msg)
|
||||
|
||||
wait_to_complete_state_transition(compute_api=compute_api, server=server)
|
||||
|
||||
return response
|
||||
|
||||
|
||||
def present_strategy(compute_api, wished_server):
|
||||
compute_api.module.debug("Starting present strategy")
|
||||
changed = False
|
||||
query_results = find(compute_api=compute_api, wished_server=wished_server, per_page=1)
|
||||
|
||||
if not query_results:
|
||||
changed = True
|
||||
if compute_api.module.check_mode:
|
||||
return changed, {"status": "A server would be created."}
|
||||
|
||||
target_server = create_server(compute_api=compute_api, server=wished_server)
|
||||
else:
|
||||
target_server = query_results[0]
|
||||
|
||||
if server_attributes_should_be_changed(compute_api=compute_api, target_server=target_server,
|
||||
wished_server=wished_server):
|
||||
changed = True
|
||||
|
||||
if compute_api.module.check_mode:
|
||||
return changed, {"status": "Server %s attributes would be changed." % target_server["id"]}
|
||||
|
||||
server_change_attributes(compute_api=compute_api, target_server=target_server, wished_server=wished_server)
|
||||
|
||||
return changed, target_server
|
||||
|
||||
|
||||
def absent_strategy(compute_api, wished_server):
|
||||
compute_api.module.debug("Starting absent strategy")
|
||||
changed = False
|
||||
target_server = None
|
||||
query_results = find(compute_api=compute_api, wished_server=wished_server, per_page=1)
|
||||
|
||||
if not query_results:
|
||||
return changed, {"status": "Server already absent."}
|
||||
else:
|
||||
target_server = query_results[0]
|
||||
|
||||
changed = True
|
||||
|
||||
if compute_api.module.check_mode:
|
||||
return changed, {"status": "Server %s would be made absent." % target_server["id"]}
|
||||
|
||||
# A server MUST be stopped to be deleted.
|
||||
while not fetch_state(compute_api=compute_api, server=target_server) == "stopped":
|
||||
wait_to_complete_state_transition(compute_api=compute_api, server=target_server)
|
||||
response = stop_server(compute_api=compute_api, server=target_server)
|
||||
|
||||
if not response.ok:
|
||||
err_msg = 'Error while stopping a server before removing it [{0}: {1}]'.format(response.status_code,
|
||||
response.json)
|
||||
compute_api.module.fail_json(msg=err_msg)
|
||||
|
||||
wait_to_complete_state_transition(compute_api=compute_api, server=target_server)
|
||||
|
||||
response = remove_server(compute_api=compute_api, server=target_server)
|
||||
|
||||
if not response.ok:
|
||||
err_msg = 'Error while removing server [{0}: {1}]'.format(response.status_code, response.json)
|
||||
compute_api.module.fail_json(msg=err_msg)
|
||||
|
||||
return changed, {"status": "Server %s deleted" % target_server["id"]}
|
||||
|
||||
|
||||
def running_strategy(compute_api, wished_server):
|
||||
compute_api.module.debug("Starting running strategy")
|
||||
changed = False
|
||||
query_results = find(compute_api=compute_api, wished_server=wished_server, per_page=1)
|
||||
|
||||
if not query_results:
|
||||
changed = True
|
||||
if compute_api.module.check_mode:
|
||||
return changed, {"status": "A server would be created before being run."}
|
||||
|
||||
target_server = create_server(compute_api=compute_api, server=wished_server)
|
||||
else:
|
||||
target_server = query_results[0]
|
||||
|
||||
if server_attributes_should_be_changed(compute_api=compute_api, target_server=target_server,
|
||||
wished_server=wished_server):
|
||||
changed = True
|
||||
|
||||
if compute_api.module.check_mode:
|
||||
return changed, {"status": "Server %s attributes would be changed before running it." % target_server["id"]}
|
||||
|
||||
server_change_attributes(compute_api=compute_api, target_server=target_server, wished_server=wished_server)
|
||||
|
||||
current_state = fetch_state(compute_api=compute_api, server=target_server)
|
||||
if current_state not in ("running", "starting"):
|
||||
compute_api.module.debug("running_strategy: Server in state: %s" % current_state)
|
||||
changed = True
|
||||
|
||||
if compute_api.module.check_mode:
|
||||
return changed, {"status": "Server %s attributes would be changed." % target_server["id"]}
|
||||
|
||||
response = start_server(compute_api=compute_api, server=target_server)
|
||||
if not response.ok:
|
||||
msg = 'Error while running server [{0}: {1}]'.format(response.status_code, response.json)
|
||||
compute_api.module.fail_json(msg=msg)
|
||||
|
||||
return changed, target_server
|
||||
|
||||
|
||||
def stop_strategy(compute_api, wished_server):
|
||||
compute_api.module.debug("Starting stop strategy")
|
||||
query_results = find(compute_api=compute_api, wished_server=wished_server, per_page=1)
|
||||
|
||||
changed = False
|
||||
|
||||
if not query_results:
|
||||
|
||||
if compute_api.module.check_mode:
|
||||
return changed, {"status": "A server would be created before being stopped."}
|
||||
|
||||
target_server = create_server(compute_api=compute_api, server=wished_server)
|
||||
changed = True
|
||||
else:
|
||||
target_server = query_results[0]
|
||||
|
||||
compute_api.module.debug("stop_strategy: Servers are found.")
|
||||
|
||||
if server_attributes_should_be_changed(compute_api=compute_api, target_server=target_server,
|
||||
wished_server=wished_server):
|
||||
changed = True
|
||||
|
||||
if compute_api.module.check_mode:
|
||||
return changed, {
|
||||
"status": "Server %s attributes would be changed before stopping it." % target_server["id"]}
|
||||
|
||||
server_change_attributes(compute_api=compute_api, target_server=target_server, wished_server=wished_server)
|
||||
|
||||
wait_to_complete_state_transition(compute_api=compute_api, server=target_server)
|
||||
|
||||
current_state = fetch_state(compute_api=compute_api, server=target_server)
|
||||
if current_state not in ("stopped",):
|
||||
compute_api.module.debug("stop_strategy: Server in state: %s" % current_state)
|
||||
|
||||
changed = True
|
||||
|
||||
if compute_api.module.check_mode:
|
||||
return changed, {"status": "Server %s would be stopped." % target_server["id"]}
|
||||
|
||||
response = stop_server(compute_api=compute_api, server=target_server)
|
||||
compute_api.module.debug(response.json)
|
||||
compute_api.module.debug(response.ok)
|
||||
|
||||
if not response.ok:
|
||||
msg = 'Error while stopping server [{0}: {1}]'.format(response.status_code, response.json)
|
||||
compute_api.module.fail_json(msg=msg)
|
||||
|
||||
return changed, target_server
|
||||
|
||||
|
||||
def restart_strategy(compute_api, wished_server):
|
||||
compute_api.module.debug("Starting restart strategy")
|
||||
changed = False
|
||||
query_results = find(compute_api=compute_api, wished_server=wished_server, per_page=1)
|
||||
|
||||
if not query_results:
|
||||
changed = True
|
||||
if compute_api.module.check_mode:
|
||||
return changed, {"status": "A server would be created before being rebooted."}
|
||||
|
||||
target_server = create_server(compute_api=compute_api, server=wished_server)
|
||||
else:
|
||||
target_server = query_results[0]
|
||||
|
||||
if server_attributes_should_be_changed(compute_api=compute_api,
|
||||
target_server=target_server,
|
||||
wished_server=wished_server):
|
||||
changed = True
|
||||
|
||||
if compute_api.module.check_mode:
|
||||
return changed, {
|
||||
"status": "Server %s attributes would be changed before rebooting it." % target_server["id"]}
|
||||
|
||||
server_change_attributes(compute_api=compute_api, target_server=target_server, wished_server=wished_server)
|
||||
|
||||
changed = True
|
||||
if compute_api.module.check_mode:
|
||||
return changed, {"status": "Server %s would be rebooted." % target_server["id"]}
|
||||
|
||||
wait_to_complete_state_transition(compute_api=compute_api, server=target_server)
|
||||
|
||||
if fetch_state(compute_api=compute_api, server=target_server) in ("running",):
|
||||
response = restart_server(compute_api=compute_api, server=target_server)
|
||||
wait_to_complete_state_transition(compute_api=compute_api, server=target_server)
|
||||
if not response.ok:
|
||||
msg = 'Error while restarting server that was running [{0}: {1}].'.format(response.status_code,
|
||||
response.json)
|
||||
compute_api.module.fail_json(msg=msg)
|
||||
|
||||
if fetch_state(compute_api=compute_api, server=target_server) in ("stopped",):
|
||||
response = restart_server(compute_api=compute_api, server=target_server)
|
||||
wait_to_complete_state_transition(compute_api=compute_api, server=target_server)
|
||||
if not response.ok:
|
||||
msg = 'Error while restarting server that was stopped [{0}: {1}].'.format(response.status_code,
|
||||
response.json)
|
||||
compute_api.module.fail_json(msg=msg)
|
||||
|
||||
return changed, target_server
|
||||
|
||||
|
||||
state_strategy = {
|
||||
"present": present_strategy,
|
||||
"restarted": restart_strategy,
|
||||
"stopped": stop_strategy,
|
||||
"running": running_strategy,
|
||||
"absent": absent_strategy
|
||||
}
|
||||
|
||||
|
||||
def find(compute_api, wished_server, per_page=1):
|
||||
compute_api.module.debug("Getting inside find")
|
||||
# Only the name attribute is accepted in the Compute query API
|
||||
url = 'servers?name=%s&per_page=%d' % (urlquote(wished_server["name"]), per_page)
|
||||
response = compute_api.get(url)
|
||||
|
||||
if not response.ok:
|
||||
msg = 'Error during server search: (%s) %s' % (response.status_code, response.json)
|
||||
compute_api.module.fail_json(msg=msg)
|
||||
|
||||
search_results = response.json["servers"]
|
||||
|
||||
return search_results
|
||||
|
||||
|
||||
PATCH_MUTABLE_SERVER_ATTRIBUTES = (
|
||||
"ipv6",
|
||||
"tags",
|
||||
"name",
|
||||
"dynamic_ip_required",
|
||||
)
|
||||
|
||||
|
||||
def server_attributes_should_be_changed(compute_api, target_server, wished_server):
|
||||
compute_api.module.debug("Checking if server attributes should be changed")
|
||||
compute_api.module.debug("Current Server: %s" % target_server)
|
||||
compute_api.module.debug("Wished Server: %s" % wished_server)
|
||||
debug_dict = dict((x, (target_server[x], wished_server[x]))
|
||||
for x in PATCH_MUTABLE_SERVER_ATTRIBUTES
|
||||
if x in target_server and x in wished_server)
|
||||
compute_api.module.debug("Debug dict %s" % debug_dict)
|
||||
|
||||
try:
|
||||
return any([target_server[x] != wished_server[x]
|
||||
for x in PATCH_MUTABLE_SERVER_ATTRIBUTES
|
||||
if x in target_server and x in wished_server])
|
||||
except AttributeError:
|
||||
compute_api.module.fail_json(msg="Error while checking if attributes should be changed")
|
||||
|
||||
|
||||
def server_change_attributes(compute_api, target_server, wished_server):
|
||||
compute_api.module.debug("Starting patching server attributes")
|
||||
patch_payload = dict((x, wished_server[x])
|
||||
for x in PATCH_MUTABLE_SERVER_ATTRIBUTES
|
||||
if x in wished_server and x in target_server)
|
||||
response = compute_api.patch(path="servers/%s" % target_server["id"],
|
||||
data=patch_payload)
|
||||
if not response.ok:
|
||||
msg = 'Error during server attributes patching: (%s) %s' % (response.status_code, response.json)
|
||||
compute_api.module.fail_json(msg=msg)
|
||||
|
||||
wait_to_complete_state_transition(compute_api=compute_api, server=target_server)
|
||||
|
||||
return response
|
||||
|
||||
|
||||
def core(module):
|
||||
region = module.params["region"]
|
||||
wished_server = {
|
||||
"state": module.params["state"],
|
||||
"image": module.params["image"],
|
||||
"name": module.params["name"],
|
||||
"commercial_type": module.params["commercial_type"],
|
||||
"enable_ipv6": module.params["enable_ipv6"],
|
||||
"boot_type": module.params["boot_type"],
|
||||
"tags": module.params["tags"],
|
||||
"organization": module.params["organization"]
|
||||
}
|
||||
module.params['api_url'] = SCALEWAY_LOCATION[region]["api_endpoint"]
|
||||
|
||||
compute_api = Scaleway(module=module)
|
||||
|
||||
changed, summary = state_strategy[wished_server["state"]](compute_api=compute_api, wished_server=wished_server)
|
||||
module.exit_json(changed=changed, msg=summary)
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = scaleway_argument_spec()
|
||||
argument_spec.update(dict(
|
||||
image=dict(required=True),
|
||||
name=dict(),
|
||||
region=dict(required=True, choices=SCALEWAY_LOCATION.keys()),
|
||||
commercial_type=dict(required=True, choices=SCALEWAY_COMMERCIAL_TYPES),
|
||||
enable_ipv6=dict(default=False, type="bool"),
|
||||
boot_type=dict(default="bootscript"),
|
||||
state=dict(choices=state_strategy.keys(), default='present'),
|
||||
tags=dict(type="list", default=[]),
|
||||
organization=dict(required=True),
|
||||
wait=dict(type="bool", default=False),
|
||||
wait_timeout=dict(type="int", default=300),
|
||||
wait_sleep_time=dict(type="int", default=3),
|
||||
))
|
||||
module = AnsibleModule(
|
||||
argument_spec=argument_spec,
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
core(module)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
14
main.yml
14
main.yml
|
@ -2,11 +2,19 @@
|
|||
- hosts: localhost
|
||||
become: false
|
||||
tasks:
|
||||
- name: Verify Ansible meets Drupal VM's version requirements.
|
||||
- name: Ensure the requirements installed
|
||||
debug:
|
||||
msg: "{{ '' | ipaddr }}"
|
||||
ignore_errors: true
|
||||
no_log: true
|
||||
register: ipaddr
|
||||
|
||||
- name: Verify Ansible meets Algo VPN requirements.
|
||||
assert:
|
||||
that: "ansible_version.full is version('2.7.10', '==')"
|
||||
that:
|
||||
- ansible_version.full is version('2.7.10', '==')
|
||||
- not ipaddr.failed
|
||||
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
|
||||
|
||||
|
|
|
@ -4,12 +4,14 @@
|
|||
shell: >
|
||||
./algo-showenv.sh \
|
||||
'algo_provider "{{ algo_provider }}"' \
|
||||
{% if ipsec_enabled %}
|
||||
'algo_ondemand_cellular "{{ algo_ondemand_cellular }}"' \
|
||||
'algo_ondemand_wifi "{{ algo_ondemand_wifi }}"' \
|
||||
'algo_ondemand_wifi_exclude "{{ algo_ondemand_wifi_exclude }}"' \
|
||||
'algo_windows "{{ algo_windows }}"' \
|
||||
{% endif %}
|
||||
'algo_local_dns "{{ algo_local_dns }}"' \
|
||||
'algo_ssh_tunneling "{{ algo_ssh_tunneling }}"' \
|
||||
'algo_windows "{{ algo_windows }}"' \
|
||||
'wireguard_enabled "{{ wireguard_enabled }}"' \
|
||||
'dns_encryption "{{ dns_encryption }}"' \
|
||||
> /dev/tty
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
ansible==2.7.10
|
||||
netaddr
|
||||
|
|
|
@ -5,3 +5,4 @@ ec2_vpc_nets:
|
|||
cidr_block: 172.16.0.0/16
|
||||
subnet_cidr: 172.16.254.0/23
|
||||
ec2_venv: "{{ playbook_dir }}/configs/.venvs/aws"
|
||||
existing_eip: ""
|
||||
|
|
|
@ -11,6 +11,12 @@ Parameters:
|
|||
Type: String
|
||||
WireGuardPort:
|
||||
Type: String
|
||||
UseThisElasticIP:
|
||||
Type: String
|
||||
Default: ''
|
||||
Conditions:
|
||||
AllocateNewEIP: !Equals [!Ref UseThisElasticIP, '']
|
||||
AssociateExistingEIP: !Not [!Equals [!Ref UseThisElasticIP, '']]
|
||||
Resources:
|
||||
VPC:
|
||||
Type: AWS::EC2::VPC
|
||||
|
@ -175,6 +181,7 @@ Resources:
|
|||
|
||||
ElasticIP:
|
||||
Type: AWS::EC2::EIP
|
||||
Condition: AllocateNewEIP
|
||||
Properties:
|
||||
Domain: vpc
|
||||
InstanceId: !Ref EC2Instance
|
||||
|
@ -182,6 +189,14 @@ Resources:
|
|||
- EC2Instance
|
||||
- VPCGatewayAttachment
|
||||
|
||||
ElasticIPAssociation:
|
||||
Type: AWS::EC2::EIPAssociation
|
||||
Condition: AssociateExistingEIP
|
||||
Properties:
|
||||
AllocationId: !Ref UseThisElasticIP
|
||||
InstanceId: !Ref EC2Instance
|
||||
|
||||
|
||||
Outputs:
|
||||
ElasticIP:
|
||||
Value: !Ref ElasticIP
|
||||
Value: !GetAtt [EC2Instance, PublicIp]
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
PublicSSHKeyParameter: "{{ lookup('file', SSH_keys.public) }}"
|
||||
ImageIdParameter: "{{ ami_image }}"
|
||||
WireGuardPort: "{{ wireguard_port }}"
|
||||
UseThisElasticIP: "{{ existing_eip }}"
|
||||
tags:
|
||||
Environment: Algo
|
||||
register: stack
|
||||
|
|
|
@ -6,13 +6,6 @@
|
|||
- name: Include prompts
|
||||
import_tasks: prompts.yml
|
||||
|
||||
- set_fact:
|
||||
algo_region: >-
|
||||
{% if region is defined %}{{ region }}
|
||||
{%- 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('.', '-') }}"
|
||||
|
||||
- name: Locate official AMI for region
|
||||
ec2_ami_facts:
|
||||
aws_access_key: "{{ access_key }}"
|
||||
|
|
|
@ -53,3 +53,36 @@
|
|||
[{{ default_region }}]
|
||||
register: _algo_region
|
||||
when: region is undefined
|
||||
|
||||
- name: Set algo_region and stack_name facts
|
||||
set_fact:
|
||||
algo_region: >-
|
||||
{% if region is defined %}{{ region }}
|
||||
{%- 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('.', '-') }}"
|
||||
|
||||
- block:
|
||||
- name: Get existing available Elastic IPs
|
||||
ec2_eip_facts:
|
||||
aws_access_key: "{{ access_key }}"
|
||||
aws_secret_key: "{{ secret_key }}"
|
||||
region: "{{ algo_region }}"
|
||||
register: raw_eip_addresses
|
||||
|
||||
- set_fact:
|
||||
available_eip_addresses: "{{ raw_eip_addresses.addresses | selectattr('association_id', 'undefined') | list }}"
|
||||
|
||||
- pause:
|
||||
prompt: >-
|
||||
What Elastic IP would you like to use?
|
||||
{% for eip in available_eip_addresses %}
|
||||
{{ loop.index }}. {{ eip['public_ip'] }}
|
||||
{% endfor %}
|
||||
|
||||
Enter the number of your desired Elastic IP
|
||||
register: _use_existing_eip
|
||||
|
||||
- set_fact:
|
||||
existing_eip: "{{ available_eip_addresses[_use_existing_eip.user_input | int -1 ]['allocation_id'] }}"
|
||||
when: cloud_providers.ec2.use_existing_eip
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
- name: Set image id as a fact
|
||||
set_fact:
|
||||
image_id: "{{ item.id }}"
|
||||
no_log: true
|
||||
when:
|
||||
- cloud_providers.scaleway.image == item.name
|
||||
- cloud_providers.scaleway.arch == item.arch
|
||||
- server_disk_size == item.root_volume.size
|
||||
with_items: "{{ outer_item['json']['images'] }}"
|
|
@ -1,133 +1,46 @@
|
|||
- name: Include prompts
|
||||
import_tasks: prompts.yml
|
||||
|
||||
- name: Set disk size
|
||||
set_fact:
|
||||
server_disk_size: 50000000000
|
||||
|
||||
- name: Check server size
|
||||
set_fact:
|
||||
server_disk_size: 25000000000
|
||||
when: cloud_providers.scaleway.size == "START1-XS"
|
||||
|
||||
- name: Check if server exists
|
||||
uri:
|
||||
url: "https://cp-{{ algo_region }}.scaleway.com/servers"
|
||||
method: GET
|
||||
headers:
|
||||
Content-Type: 'application/json'
|
||||
X-Auth-Token: "{{ algo_scaleway_token }}"
|
||||
status_code: 200
|
||||
register: scaleway_servers
|
||||
|
||||
- name: Set server id as a fact
|
||||
set_fact:
|
||||
server_id: "{{ item.id }}"
|
||||
no_log: true
|
||||
when: algo_server_name == item.name
|
||||
with_items: "{{ scaleway_servers.json.servers }}"
|
||||
|
||||
- name: Create a server if it doesn't exist
|
||||
block:
|
||||
- name: Get the organization id
|
||||
uri:
|
||||
url: https://account.cloud.online.net/organizations
|
||||
method: GET
|
||||
headers:
|
||||
Content-Type: 'application/json'
|
||||
X-Auth-Token: "{{ algo_scaleway_token }}"
|
||||
status_code: 200
|
||||
register: scaleway_organizations
|
||||
|
||||
- name: Set organization id as a fact
|
||||
set_fact:
|
||||
organization_id: "{{ item.id }}"
|
||||
no_log: true
|
||||
when: algo_scaleway_org == item.name
|
||||
with_items: "{{ scaleway_organizations.json.organizations }}"
|
||||
|
||||
- name: Get total count of images
|
||||
uri:
|
||||
url: "https://cp-{{ algo_region }}.scaleway.com/images"
|
||||
method: GET
|
||||
headers:
|
||||
Content-Type: 'application/json'
|
||||
X-Auth-Token: "{{ algo_scaleway_token }}"
|
||||
status_code: 200
|
||||
register: scaleway_pages
|
||||
- block:
|
||||
- name: Gather Scaleway organizations facts
|
||||
scaleway_organization_facts:
|
||||
|
||||
- name: Get images
|
||||
uri:
|
||||
url: "https://cp-{{ algo_region }}.scaleway.com/images?per_page=100&page={{ item }}"
|
||||
method: GET
|
||||
headers:
|
||||
Content-Type: 'application/json'
|
||||
X-Auth-Token: "{{ algo_scaleway_token }}"
|
||||
status_code: 200
|
||||
register: scaleway_images
|
||||
with_sequence: start=1 end={{ ((scaleway_pages.x_total_count|int / 100)| round )|int }}
|
||||
scaleway_image_facts:
|
||||
region: "{{ algo_region }}"
|
||||
|
||||
- name: Set image id as a fact
|
||||
include_tasks: image_facts.yml
|
||||
with_items: "{{ scaleway_images['results'] }}"
|
||||
loop_control:
|
||||
loop_var: outer_item
|
||||
- name: Set cloud specific facts
|
||||
set_fact:
|
||||
organization_id: "{{ scaleway_organization_facts[0]['id'] }}"
|
||||
images: >-
|
||||
[{% for i in scaleway_image_facts -%}
|
||||
{% if i.name == cloud_providers.scaleway.image and
|
||||
i.arch == cloud_providers.scaleway.arch -%}
|
||||
'{{ i.id }}'{% if not loop.last %},{% endif %}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}]
|
||||
|
||||
- name: Create a server
|
||||
uri:
|
||||
url: "https://cp-{{ algo_region }}.scaleway.com/servers/"
|
||||
method: POST
|
||||
headers:
|
||||
Content-Type: 'application/json'
|
||||
X-Auth-Token: "{{ algo_scaleway_token }}"
|
||||
body:
|
||||
organization: "{{ organization_id }}"
|
||||
name: "{{ algo_server_name }}"
|
||||
image: "{{ image_id }}"
|
||||
commercial_type: "{{ cloud_providers.scaleway.size }}"
|
||||
enable_ipv6: true
|
||||
boot_type: local
|
||||
tags:
|
||||
- Environment:Algo
|
||||
- AUTHORIZED_KEY={{ lookup('file', SSH_keys.public)|regex_replace(' ', '_') }}
|
||||
status_code: 201
|
||||
body_format: json
|
||||
scaleway_compute:
|
||||
name: "{{ algo_server_name }}"
|
||||
enable_ipv6: true
|
||||
boot_type: local
|
||||
state: running
|
||||
image: "{{ images[0] }}"
|
||||
organization: "{{ organization_id }}"
|
||||
region: "{{ algo_region }}"
|
||||
commercial_type: "{{ cloud_providers.scaleway.size }}"
|
||||
wait: true
|
||||
tags:
|
||||
- Environment:Algo
|
||||
- AUTHORIZED_KEY={{ lookup('file', SSH_keys.public)|regex_replace(' ', '_') }}
|
||||
register: algo_instance
|
||||
|
||||
- name: Set server id as a fact
|
||||
set_fact:
|
||||
server_id: "{{ algo_instance.json.server.id }}"
|
||||
when: server_id is not defined
|
||||
|
||||
- name: Power on the server
|
||||
uri:
|
||||
url: https://cp-{{ algo_region }}.scaleway.com/servers/{{ server_id }}/action
|
||||
method: POST
|
||||
headers:
|
||||
Content-Type: application/json
|
||||
X-Auth-Token: "{{ algo_scaleway_token }}"
|
||||
body:
|
||||
action: poweron
|
||||
status_code: 202
|
||||
body_format: json
|
||||
ignore_errors: true
|
||||
no_log: true
|
||||
|
||||
- name: Wait for the server to become running
|
||||
uri:
|
||||
url: "https://cp-{{ algo_region }}.scaleway.com/servers/{{ server_id }}"
|
||||
method: GET
|
||||
headers:
|
||||
Content-Type: 'application/json'
|
||||
X-Auth-Token: "{{ algo_scaleway_token }}"
|
||||
status_code: 200
|
||||
until:
|
||||
- algo_instance.json.server.state is defined
|
||||
- algo_instance.json.server.state == "running"
|
||||
retries: 20
|
||||
delay: 30
|
||||
register: algo_instance
|
||||
until: algo_instance.msg.public_ip
|
||||
retries: 3
|
||||
delay: 3
|
||||
environment:
|
||||
SCW_TOKEN: "{{ algo_scaleway_token }}"
|
||||
|
||||
- set_fact:
|
||||
cloud_instance_ip: "{{ algo_instance['json']['server']['public_ip']['address'] }}"
|
||||
cloud_instance_ip: "{{ algo_instance.msg.public_ip.address }}"
|
||||
ansible_ssh_user: root
|
||||
|
|
|
@ -1,16 +1,12 @@
|
|||
---
|
||||
- pause:
|
||||
prompt: |
|
||||
Enter your auth token (https://www.scaleway.com/docs/generate-an-api-token/)
|
||||
Enter your auth token (https://trailofbits.github.io/algo/cloud-scaleway.html)
|
||||
echo: false
|
||||
register: _scaleway_token
|
||||
when: scaleway_token is undefined
|
||||
|
||||
- pause:
|
||||
prompt: |
|
||||
Enter your organization name (https://cloud.scaleway.com/#/billing)
|
||||
register: _scaleway_org
|
||||
when: scaleway_org is undefined
|
||||
when:
|
||||
- scaleway_token is undefined
|
||||
- lookup('env','SCW_TOKEN')|length <= 0
|
||||
|
||||
- pause:
|
||||
prompt: |
|
||||
|
@ -26,8 +22,7 @@
|
|||
|
||||
- name: Set scaleway facts
|
||||
set_fact:
|
||||
algo_scaleway_token: "{{ scaleway_token | default(_scaleway_token.user_input) }}"
|
||||
algo_scaleway_org: "{{ scaleway_org | default(_scaleway_org.user_input|default(omit)) }}"
|
||||
algo_scaleway_token: "{{ scaleway_token | default(_scaleway_token.user_input) | default(lookup('env','SCW_TOKEN'), true) }}"
|
||||
algo_region: >-
|
||||
{% if region is defined %}{{ region }}
|
||||
{%- elif _algo_region.user_input %}{{ scaleway_regions[_algo_region.user_input | int -1 ]['alias'] }}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
ifconfig lo100 destroy || true &&
|
||||
ifconfig lo100 create &&
|
||||
ifconfig lo100 inet {{ local_service_ip }} netmask 255.255.255.255 &&
|
||||
ifconfig lo100 inet6 FCAA::1/64; echo $?
|
||||
ifconfig lo100 inet6 {{ local_service_ipv6 }}/128; echo $?
|
||||
|
||||
- name: restart iptables
|
||||
service: name=netfilter-persistent state=restarted
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
block: |
|
||||
cloned_interfaces="lo100"
|
||||
ifconfig_lo100="inet {{ local_service_ip }} netmask 255.255.255.255"
|
||||
ifconfig_lo100_ipv6="inet6 FCAA::1/64"
|
||||
ifconfig_lo100_ipv6="inet6 {{ local_service_ipv6 }}/128"
|
||||
notify:
|
||||
- restart loopback bsd
|
||||
|
||||
|
|
|
@ -24,16 +24,12 @@
|
|||
when: reboot_required is defined and reboot_required.stdout == 'required'
|
||||
ignore_errors: true
|
||||
|
||||
- name: Wait until SSH becomes ready...
|
||||
wait_for:
|
||||
port: 22
|
||||
host: "{{ inventory_hostname }}"
|
||||
search_regex: OpenSSH
|
||||
delay: 10
|
||||
- name: Wait until the server becomes ready...
|
||||
wait_for_connection:
|
||||
delay: 20
|
||||
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
|
||||
|
|
|
@ -4,4 +4,4 @@ Name=lo
|
|||
[Network]
|
||||
Description=lo:100
|
||||
Address={{ local_service_ip }}/32
|
||||
Address=FCAA::1/64
|
||||
Address={{ local_service_ipv6 }}/128
|
||||
|
|
|
@ -77,6 +77,13 @@ COMMIT
|
|||
|
||||
# Drop traffic between VPN clients
|
||||
-A FORWARD -s {{ subnets|join(',') }} -d {{ subnets|join(',') }} -j {{ "DROP" if BetweenClients_DROP else "ACCEPT" }}
|
||||
# Drop traffic to VPN clients from SSH tunnels
|
||||
-A OUTPUT -d {{ subnets|join(',') }} -m owner --gid-owner 15000 -j {{ "DROP" if BetweenClients_DROP else "ACCEPT" }}
|
||||
|
||||
# Drop traffic to the link-local network
|
||||
-A FORWARD -s {{ subnets|join(',') }} -d 169.254.0.0/16 -j DROP
|
||||
# Drop traffic to the link-local network from SSH tunnels
|
||||
-A OUTPUT -d 169.254.0.0/16 -m owner --gid-owner 15000 -j DROP
|
||||
|
||||
# Forward any packet that's part of an established connection
|
||||
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
||||
|
|
|
@ -83,10 +83,12 @@ COMMIT
|
|||
# particular virtual (tun,tap,...) or physical (ethernet) interface.
|
||||
|
||||
# Accept DNS traffic to the local DNS resolver
|
||||
-A INPUT -d fcaa::1 -p udp --dport 53 -j ACCEPT
|
||||
-A INPUT -d {{ local_service_ipv6 }}/128 -p udp --dport 53 -j ACCEPT
|
||||
|
||||
# Drop traffic between VPN clients
|
||||
-A FORWARD -s {{ subnets|join(',') }} -d {{ subnets|join(',') }} -j {{ "DROP" if BetweenClients_DROP else "ACCEPT" }}
|
||||
# Drop traffic to VPN clients from SSH tunnels
|
||||
-A OUTPUT -d {{ subnets|join(',') }} -m owner --gid-owner 15000 -j {{ "DROP" if BetweenClients_DROP else "ACCEPT" }}
|
||||
|
||||
-A FORWARD -j ICMPV6-CHECK
|
||||
-A FORWARD -p tcp --dport 445 -j DROP
|
||||
|
|
|
@ -90,6 +90,9 @@ no-resolv
|
|||
# server=10.1.2.3@eth1
|
||||
{% if dns_encryption %}
|
||||
server={{ local_service_ip }}#5353
|
||||
{% if ipv6_support -%}
|
||||
server={{ local_service_ipv6 }}#5353
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% for host in dns_servers.ipv4 %}
|
||||
server={{ host }}
|
||||
|
@ -116,7 +119,7 @@ group=nogroup
|
|||
#except-interface=
|
||||
# Or which to listen on by address (remember to include 127.0.0.1 if
|
||||
# you use this.)
|
||||
listen-address=127.0.0.1,FCAA::1,{{ local_service_ip }}
|
||||
listen-address=127.0.0.1,{{ local_service_ipv6 }},{{ local_service_ip }}
|
||||
# If you want dnsmasq to provide only DNS service on an interface,
|
||||
# configure it as shown above, and then use the following line to
|
||||
# disable DHCP and TFTP on it.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include <tunables/global>
|
||||
|
||||
/usr/bin/dnscrypt-proxy flags=(attach_disconnected) {
|
||||
/usr/{s,}bin/dnscrypt-proxy flags=(attach_disconnected) {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/openssl>
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
- name: Add the repository
|
||||
apt_repository:
|
||||
state: present
|
||||
codename: bionic
|
||||
codename: "{{ ansible_distribution_release }}"
|
||||
repo: ppa:shevchuk/dnscrypt-proxy
|
||||
when: ansible_distribution_version is version_compare('19.04', '<')
|
||||
register: result
|
||||
until: result is succeeded
|
||||
retries: 10
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
## List of local addresses and ports to listen to. Can be IPv4 and/or IPv6.
|
||||
## Note: When using systemd socket activation, choose an empty set (i.e. [] ).
|
||||
|
||||
listen_addresses = ['{{ local_service_ip }}:{{ listen_port }}']
|
||||
listen_addresses = ['{{ local_service_ip }}:{{ listen_port }}'{% if ipv6_support %}, '[{{ local_service_ipv6 }}]:{{ listen_port }}'{% endif %}]
|
||||
|
||||
|
||||
## Maximum number of simultaneous client connections to accept
|
||||
|
|
|
@ -13,21 +13,21 @@
|
|||
{%- elif _algo_server.user_input %}{{ _algo_server.user_input }}
|
||||
{%- else %}localhost{% endif %}
|
||||
|
||||
- pause:
|
||||
prompt: |
|
||||
What user should we use to login on the server? (note: passwordless login required, or ignore if you're deploying to localhost)
|
||||
[root]
|
||||
register: _algo_ssh_user
|
||||
when:
|
||||
- ssh_user is undefined
|
||||
- cloud_instance_ip != "localhost"
|
||||
- block:
|
||||
- pause:
|
||||
prompt: |
|
||||
What user should we use to login on the server? (note: passwordless login required, or ignore if you're deploying to localhost)
|
||||
[root]
|
||||
register: _algo_ssh_user
|
||||
when: ssh_user is undefined
|
||||
|
||||
- name: Set the facts
|
||||
set_fact:
|
||||
ansible_ssh_user: >-
|
||||
{% if ssh_user is defined %}{{ ssh_user }}
|
||||
{%- elif _algo_ssh_user.user_input %}{{ _algo_ssh_user.user_input }}
|
||||
{%- else %}root{% endif %}
|
||||
- name: Set the facts
|
||||
set_fact:
|
||||
ansible_ssh_user: >-
|
||||
{% if ssh_user is defined %}{{ ssh_user }}
|
||||
{%- elif _algo_ssh_user.user_input %}{{ _algo_ssh_user.user_input }}
|
||||
{%- else %}root{% endif %}
|
||||
when: cloud_instance_ip != "localhost"
|
||||
|
||||
- pause:
|
||||
prompt: |
|
||||
|
|
|
@ -14,7 +14,10 @@
|
|||
- restart ssh
|
||||
|
||||
- name: Ensure that the algo group exist
|
||||
group: name=algo state=present
|
||||
group:
|
||||
name: algo
|
||||
state: present
|
||||
gid: 15000
|
||||
|
||||
- name: Ensure that the jail directory exist
|
||||
file:
|
||||
|
@ -28,7 +31,7 @@
|
|||
- name: Ensure that the SSH users exist
|
||||
user:
|
||||
name: "{{ item }}"
|
||||
groups: algo
|
||||
group: algo
|
||||
home: '/var/jail/{{ item }}'
|
||||
createhome: yes
|
||||
generate_ssh_key: false
|
||||
|
|
|
@ -10,17 +10,26 @@
|
|||
update_cache: yes
|
||||
install_recommends: yes
|
||||
|
||||
- name: Ubuntu | Enforcing ipsec with apparmor
|
||||
command: aa-enforce "{{ item }}"
|
||||
- block:
|
||||
# https://bugs.launchpad.net/ubuntu/+source/strongswan/+bug/1826238
|
||||
- name: Ubuntu | Charon profile for apparmor configured
|
||||
copy:
|
||||
dest: /etc/apparmor.d/local/usr.lib.ipsec.charon
|
||||
content: ' capability setpcap,'
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0644
|
||||
notify: restart strongswan
|
||||
|
||||
- name: Ubuntu | Enforcing ipsec with apparmor
|
||||
command: aa-enforce "{{ item }}"
|
||||
changed_when: false
|
||||
with_items:
|
||||
- /usr/lib/ipsec/charon
|
||||
- /usr/lib/ipsec/lookip
|
||||
- /usr/lib/ipsec/stroke
|
||||
tags: apparmor
|
||||
when: apparmor_enabled|default(false)|bool
|
||||
changed_when: false
|
||||
with_items:
|
||||
- /usr/lib/ipsec/charon
|
||||
- /usr/lib/ipsec/lookip
|
||||
- /usr/lib/ipsec/stroke
|
||||
notify:
|
||||
- restart apparmor
|
||||
tags: ['apparmor']
|
||||
|
||||
- name: Ubuntu | Enable services
|
||||
service: name={{ item }} enabled=yes
|
||||
|
|
|
@ -31,7 +31,7 @@ conn %default
|
|||
rightauth=pubkey
|
||||
rightsourceip={{ strongswan_network }},{{ strongswan_network_ipv6 }}
|
||||
{% if algo_local_dns or dns_encryption %}
|
||||
rightdns={{ local_service_ip }}
|
||||
rightdns={{ local_service_ip }}{{ ',' + local_service_ipv6 if ipv6_support else '' }}
|
||||
{% else %}
|
||||
rightdns={% 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 %}
|
||||
{% endif %}
|
||||
|
|
|
@ -6,9 +6,13 @@ wireguard_interface: wg0
|
|||
keys_clean_all: false
|
||||
wireguard_dns_servers: >-
|
||||
{% if local_dns|default(false)|bool or dns_encryption|default(false)|bool %}
|
||||
{{ local_service_ip }}
|
||||
{{ local_service_ip }}{{ ', ' + local_service_ipv6 if ipv6_support 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 %}
|
||||
{% endif %}
|
||||
wireguard_client_ip: "{{ _wireguard_network_ipv4['clients_range'] }}.{{ _wireguard_network_ipv4['clients_start'] + index|int + 1 }}/{{ _wireguard_network_ipv4['prefix'] }}{% if ipv6_support %},{{ _wireguard_network_ipv6['clients_range'] }}{{ _wireguard_network_ipv6['clients_start'] + index|int + 1 }}/{{ _wireguard_network_ipv6['prefix'] }}{% endif %}"
|
||||
wireguard_server_ip: "{{ _wireguard_network_ipv4['gateway'] }}/{{ _wireguard_network_ipv4['prefix'] }}{% if ipv6_support %},{{ _wireguard_network_ipv6['gateway'] }}/{{ _wireguard_network_ipv6['prefix'] }}{% endif %}"
|
||||
wireguard_client_ip: >-
|
||||
{{ wireguard_network_ipv4 | ipaddr(index|int+2) }}
|
||||
{{ ',' + wireguard_network_ipv6 | ipaddr(index|int+2) if ipv6_support else '' }}
|
||||
wireguard_server_ip: >-
|
||||
{{ wireguard_network_ipv4 | ipaddr('1') }}
|
||||
{{ ',' + wireguard_network_ipv6 | ipaddr('1') if ipv6_support else '' }}
|
||||
|
|
|
@ -11,7 +11,6 @@ SaveConfig = false
|
|||
[Peer]
|
||||
# {{ u }}
|
||||
PublicKey = {{ lookup('file', wireguard_pki_path + '/public/' + u) }}
|
||||
AllowedIPs = {{ _wireguard_network_ipv4['clients_range'] }}.{{ _wireguard_network_ipv4['clients_start'] + index }}/32{% if ipv6_support %},{{ _wireguard_network_ipv6['clients_range'] }}{{ _wireguard_network_ipv6['clients_start'] + index }}/128{% endif %}
|
||||
|
||||
AllowedIPs = {{ wireguard_network_ipv4 | ipaddr(index|int+1) | ipv4('address') }}/32{{ ',' + wireguard_network_ipv6 | ipaddr(index|int+1) | ipv6('address') + '/128' if ipv6_support else '' }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
|
|
@ -10,7 +10,7 @@ export LOCAL_DNS=true
|
|||
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 EXTRA_VARS='install_headers=false tests=true apparmor_enabled=false local_service_ip=172.16.0.1'
|
||||
export ANSIBLE_EXTRA_ARGS='--skip-tags apparmor'
|
||||
export REPO_SLUG=${TRAVIS_PULL_REQUEST_SLUG:-${TRAVIS_REPO_SLUG:-trailofbits/algo}}
|
||||
export REPO_BRANCH=${TRAVIS_PULL_REQUEST_BRANCH:-${TRAVIS_BRANCH:-master}}
|
||||
|
|
|
@ -21,3 +21,5 @@ 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"
|
||||
|
||||
ipsec down algovpn-10.0.8.100
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
set -ex
|
||||
|
||||
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"
|
||||
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 local_service_ip=172.16.0.1"
|
||||
|
||||
if [ "${DEPLOY}" == "docker" ]
|
||||
then
|
||||
|
|
|
@ -19,7 +19,7 @@ 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
|
||||
lxc launch ubuntu:${UBUNTU_VERSION} algo
|
||||
|
||||
ip addr
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
set -ex
|
||||
|
||||
USER_ARGS="{ 'server': '10.0.8.100', 'users': ['desktop', 'user1', 'user2'] }"
|
||||
USER_ARGS="{ 'server': '10.0.8.100', 'users': ['desktop', 'user1', 'user2'], 'local_service_ip': '172.16.0.1' }"
|
||||
|
||||
if [ "${DEPLOY}" == "docker" ]
|
||||
then
|
||||
|
|
|
@ -19,3 +19,5 @@ wg | grep "latest handshake"
|
|||
host google.com 172.16.0.1
|
||||
|
||||
echo "WireGuard tests passed"
|
||||
|
||||
wg-quick down configs/10.0.8.100/wireguard/user1.conf
|
||||
|
|
76
users.yml
76
users.yml
|
@ -7,38 +7,70 @@
|
|||
|
||||
tasks:
|
||||
- block:
|
||||
- name: Get list of installed config files
|
||||
find:
|
||||
paths: configs/
|
||||
depth: 2
|
||||
recurse: true
|
||||
hidden: true
|
||||
patterns: ".config.yml"
|
||||
register: _configs_list
|
||||
|
||||
- name: Verify servers
|
||||
assert:
|
||||
that: _configs_list.matched > 0
|
||||
msg: No servers found, nothing to update.
|
||||
|
||||
- name: Build list of installed servers
|
||||
set_fact:
|
||||
server_list: >-
|
||||
[{% for i in _configs_list.files %}
|
||||
{% set config = lookup('file', i.path)|from_yaml %}
|
||||
'{{ config.server }}'
|
||||
{{ ',' if not loop.last else '' }}
|
||||
{% endfor %}]
|
||||
|
||||
- name: Server address prompt
|
||||
pause:
|
||||
prompt: "Enter the IP address of your server: (or use localhost for local installation)"
|
||||
prompt: |
|
||||
Select the server to update user list below:
|
||||
{% for r in server_list %}
|
||||
{{ loop.index }}. {{ r }}
|
||||
{% endfor %}
|
||||
register: _server
|
||||
when: server is undefined
|
||||
when: server is undefined
|
||||
|
||||
- block:
|
||||
- name: Set facts based on the input
|
||||
set_fact:
|
||||
algo_server: >-
|
||||
{% if server is defined %}{{ server }}
|
||||
{%- elif _server.user_input %}{{ _server.user_input }}
|
||||
{%- elif _server.user_input %}{{ server_list[_server.user_input | int -1 ] }}
|
||||
{%- else %}omit{% endif %}
|
||||
|
||||
- name: Import host specific variables
|
||||
include_vars:
|
||||
file: "configs/{{ algo_server }}/.config.yml"
|
||||
|
||||
- name: CA password prompt
|
||||
pause:
|
||||
prompt: Enter the password for the private CA key
|
||||
echo: false
|
||||
register: _ca_password
|
||||
when:
|
||||
- ca_password is undefined
|
||||
- ipsec_enabled
|
||||
- when: ipsec_enabled
|
||||
block:
|
||||
- name: CA password prompt
|
||||
pause:
|
||||
prompt: Enter the password for the private CA key
|
||||
echo: false
|
||||
register: _ca_password
|
||||
when: ca_password is undefined
|
||||
|
||||
- name: Set facts based on the input
|
||||
set_fact:
|
||||
CA_password: >-
|
||||
{% if ca_password is defined %}{{ ca_password }}
|
||||
{%- elif _ca_password.user_input %}{{ _ca_password.user_input }}
|
||||
{%- else %}omit{% endif %}
|
||||
- name: Set facts based on the input
|
||||
set_fact:
|
||||
CA_password: >-
|
||||
{% if ca_password is defined %}{{ ca_password }}
|
||||
{%- elif _ca_password.user_input %}{{ _ca_password.user_input }}
|
||||
{%- else %}omit{% endif %}
|
||||
|
||||
- name: Local pre-tasks
|
||||
import_tasks: playbooks/cloud-pre.yml
|
||||
become: false
|
||||
|
||||
- name: Add the server to the vpn-host group
|
||||
add_host:
|
||||
|
@ -47,7 +79,7 @@
|
|||
ansible_ssh_user: "{{ server_user|default('root') }}"
|
||||
ansible_connection: "{% if algo_server == 'localhost' %}local{% else %}ssh{% endif %}"
|
||||
ansible_python_interpreter: "/usr/bin/python3"
|
||||
CA_password: "{{ CA_password }}"
|
||||
CA_password: "{{ CA_password|default(omit) }}"
|
||||
rescue:
|
||||
- include_tasks: playbooks/rescue.yml
|
||||
|
||||
|
@ -61,10 +93,6 @@
|
|||
|
||||
tasks:
|
||||
- block:
|
||||
- name: Local pre-tasks
|
||||
import_tasks: playbooks/cloud-pre.yml
|
||||
become: false
|
||||
|
||||
- import_role:
|
||||
name: common
|
||||
|
||||
|
@ -84,7 +112,9 @@
|
|||
- debug:
|
||||
msg:
|
||||
- "{{ congrats.common.split('\n') }}"
|
||||
- " {% if p12.changed %}{{ congrats.p12_pass }}{% endif %}"
|
||||
- " {{ congrats.p12_pass if algo_ssh_tunneling or ipsec_enabled else '' }}"
|
||||
- " {{ congrats.ca_key_pass if algo_store_cakey and ipsec_enabled else '' }}"
|
||||
- " {{ congrats.ssh_access if algo_provider != 'local' else ''}}"
|
||||
tags: always
|
||||
rescue:
|
||||
- include_tasks: playbooks/rescue.yml
|
||||
|
|
Loading…
Add table
Reference in a new issue