forked from trailofbits/algo
-
Notifications
You must be signed in to change notification settings - Fork 0
251 lines (223 loc) · 8.26 KB
/
integration-tests.yml
File metadata and controls
251 lines (223 loc) · 8.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
---
name: Integration Tests
'on':
pull_request:
types: [opened, synchronize, reopened]
paths:
- 'main.yml'
- 'roles/**'
- 'playbooks/**'
- 'library/**'
workflow_dispatch:
schedule:
- cron: '0 2 * * 1' # Weekly on Monday at 2 AM
permissions:
contents: read
jobs:
localhost-deployment:
name: Localhost VPN Deployment Test
runs-on: ubuntu-22.04
timeout-minutes: 30
if: false # Disabled until we fix the ansible issues
strategy:
matrix:
vpn_type: ['wireguard', 'ipsec', 'both']
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.11'
cache: 'pip'
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
wireguard \
wireguard-tools \
strongswan \
libstrongswan-standard-plugins \
dnsmasq \
qrencode \
openssl \
linux-headers-$(uname -r)
- name: Install uv
run: curl -LsSf https://astral.sh/uv/install.sh | sh
- name: Install Python dependencies
run: uv sync
- name: Create test configuration
run: |
cat > integration-test.cfg << EOF
users:
- alice
- bob
cloud_providers:
local:
server: localhost
endpoint: 127.0.0.1
wireguard_enabled: ${{ matrix.vpn_type == 'wireguard' || matrix.vpn_type == 'both' }}
ipsec_enabled: ${{ matrix.vpn_type == 'ipsec' || matrix.vpn_type == 'both' }}
dns_adblocking: true
ssh_tunneling: false
store_pki: true
algo_provider: local
algo_server_name: github-ci-test
server: localhost
algo_ssh_port: 22
CA_password: "test-ca-password-${{ github.run_id }}"
p12_export_password: "test-p12-password-${{ github.run_id }}"
tests: true
no_log: false
ansible_connection: local
ansible_python_interpreter: /usr/bin/python3
dns_encryption: true
algo_dns_adblocking: true
algo_ssh_tunneling: false
BetweenClients_DROP: true
block_smb: true
block_netbios: true
pki_in_tmpfs: true
endpoint: 127.0.0.1
ssh_port: 4160
EOF
- name: Run Algo deployment
run: |
sudo ansible-playbook main.yml \
-i "localhost," \
-c local \
-e @integration-test.cfg \
-e "provider=local" \
-vv
- name: Verify services are running
run: |
# Check WireGuard
if [[ "${{ matrix.vpn_type }}" == "wireguard" || "${{ matrix.vpn_type }}" == "both" ]]; then
echo "Checking WireGuard..."
sudo wg show
if ! sudo systemctl is-active --quiet wg-quick@wg0; then
echo "✗ WireGuard service not running"
exit 1
fi
echo "✓ WireGuard is running"
fi
# Check StrongSwan
if [[ "${{ matrix.vpn_type }}" == "ipsec" || "${{ matrix.vpn_type }}" == "both" ]]; then
echo "Checking StrongSwan..."
sudo ipsec statusall
if ! sudo systemctl is-active --quiet strongswan; then
echo "✗ StrongSwan service not running"
exit 1
fi
echo "✓ StrongSwan is running"
fi
# Check dnsmasq
if ! sudo systemctl is-active --quiet dnsmasq; then
echo "⚠️ dnsmasq not running (may be expected)"
else
echo "✓ dnsmasq is running"
fi
- name: Verify generated configs
run: |
echo "Checking generated configuration files..."
# WireGuard configs
if [[ "${{ matrix.vpn_type }}" == "wireguard" || "${{ matrix.vpn_type }}" == "both" ]]; then
for user in alice bob; do
if [ ! -f "configs/localhost/wireguard/${user}.conf" ]; then
echo "✗ Missing WireGuard config for ${user}"
exit 1
fi
if [ ! -f "configs/localhost/wireguard/${user}.png" ]; then
echo "✗ Missing WireGuard QR code for ${user}"
exit 1
fi
done
echo "✓ All WireGuard configs generated"
fi
# IPsec configs
if [[ "${{ matrix.vpn_type }}" == "ipsec" || "${{ matrix.vpn_type }}" == "both" ]]; then
for user in alice bob; do
if [ ! -f "configs/localhost/ipsec/${user}.p12" ]; then
echo "✗ Missing IPsec certificate for ${user}"
exit 1
fi
if [ ! -f "configs/localhost/ipsec/${user}.mobileconfig" ]; then
echo "✗ Missing IPsec mobile config for ${user}"
exit 1
fi
done
echo "✓ All IPsec configs generated"
fi
- name: Test VPN connectivity
run: |
echo "Testing basic VPN connectivity..."
# Test WireGuard
if [[ "${{ matrix.vpn_type }}" == "wireguard" || "${{ matrix.vpn_type }}" == "both" ]]; then
# Get server's WireGuard public key
SERVER_PUBKEY=$(sudo wg show wg0 public-key)
echo "Server public key: $SERVER_PUBKEY"
# Check if interface has peers
PEER_COUNT=$(sudo wg show wg0 peers | wc -l)
echo "✓ WireGuard has $PEER_COUNT peer(s) configured"
fi
# Test StrongSwan
if [[ "${{ matrix.vpn_type }}" == "ipsec" || "${{ matrix.vpn_type }}" == "both" ]]; then
# Check IPsec policies
sudo ipsec statusall | grep -E "INSTALLED|ESTABLISHED" || echo "No active IPsec connections (expected)"
fi
- name: Upload configs as artifacts
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: vpn-configs-${{ matrix.vpn_type }}-${{ github.run_id }}
path: configs/
retention-days: 7
- name: Upload logs on failure
if: failure()
run: |
echo "=== Ansible Log ==="
sudo journalctl -u ansible --no-pager || true
echo "=== WireGuard Log ==="
sudo journalctl -u wg-quick@wg0 --no-pager || true
echo "=== StrongSwan Log ==="
sudo journalctl -u strongswan --no-pager || true
echo "=== System Log (last 100 lines) ==="
sudo journalctl -n 100 --no-pager || true
docker-build-test:
name: Docker Image Build Test
runs-on: ubuntu-22.04
timeout-minutes: 10
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- name: Build Algo Docker image
run: |
docker build -t algo:ci-test .
- name: Test Docker image
run: |
# Test that the image can run and show help
docker run --rm --entrypoint /bin/sh algo:ci-test -c "cd /algo && ./algo --help" || true
# Test that required binaries exist in the virtual environment
docker run --rm --entrypoint /bin/sh algo:ci-test -c "cd /algo && uv run which ansible"
docker run --rm --entrypoint /bin/sh algo:ci-test -c "which python3"
docker run --rm --entrypoint /bin/sh algo:ci-test -c "which rsync"
- name: Test Docker config validation
run: |
# Create a minimal valid config
mkdir -p test-data
cat > test-data/config.cfg << 'EOF'
users:
- test-user
cloud_providers:
ec2:
size: t3.micro
region: us-east-1
wireguard_enabled: true
ipsec_enabled: false
dns_encryption: true
algo_provider: ec2
EOF
# Test that config is readable
docker run --rm --entrypoint cat -v $(pwd)/test-data:/data algo:ci-test /data/config.cfg
echo "✓ Docker image built and basic tests passed"