mirror of
https://github.com/trailofbits/algo.git
synced 2026-08-17 21:25:50 +02:00
Bumps the github-actions group with 6 updates in the / directory: | Package | From | To | | --- | --- | --- | | [actions/checkout](https://github.com/actions/checkout) | `7.0.0` | `7.0.1` | | [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) | `4.1.0` | `4.2.0` | | [docker/login-action](https://github.com/docker/login-action) | `4.2.0` | `4.4.0` | | [docker/metadata-action](https://github.com/docker/metadata-action) | `6.1.0` | `6.2.0` | | [actions/setup-python](https://github.com/actions/setup-python) | `6.3.0` | `7.0.0` | | [dorny/paths-filter](https://github.com/dorny/paths-filter) | `4.0.1` | `4.0.2` | Updates `actions/checkout` from 7.0.0 to 7.0.1 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0...3d3c42e5aac5ba805825da76410c181273ba90b1) Updates `docker/setup-buildx-action` from 4.1.0 to 4.2.0 - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5...bb05f3f5519dd87d3ba754cc423b652a5edd6d2c) Updates `docker/login-action` from 4.2.0 to 4.4.0 - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/650006c6eb7dba73a995cc03b0b2d7f5ca915bee...af1e73f918a031802d376d3c8bbc3fe56130a9b0) Updates `docker/metadata-action` from 6.1.0 to 6.2.0 - [Release notes](https://github.com/docker/metadata-action/releases) - [Commits](https://github.com/docker/metadata-action/compare/80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9...dc802804100637a589fabce1cb79ff13a1411302) Updates `actions/setup-python` from 6.3.0 to 7.0.0 - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/ece7cb06caefa5fff74198d8649806c4678c61a1...5fda3b95a4ea91299a34e894583c3862153e4b97) Updates `dorny/paths-filter` from 4.0.1 to 4.0.2 - [Release notes](https://github.com/dorny/paths-filter/releases) - [Changelog](https://github.com/dorny/paths-filter/blob/master/CHANGELOG.md) - [Commits](https://github.com/dorny/paths-filter/compare/fbd0ab8f3e69293af611ebaee6363fc25e6d187d...7b450fff21473bca461d4b92ce414b9d0420d706) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: docker/setup-buildx-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: docker/login-action dependency-version: 4.4.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: docker/metadata-action dependency-version: 6.2.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: actions/setup-python dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: dorny/paths-filter dependency-version: 4.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions ... Signed-off-by: dependabot[bot] <support@github.com>
305 lines
10 KiB
YAML
305 lines
10 KiB
YAML
---
|
|
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
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
vpn_type: ['wireguard', 'ipsec', 'both']
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
with:
|
|
python-version: '3.11'
|
|
# Note: No pip cache - we use uv for dependency management
|
|
|
|
- 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)" \
|
|
libxml2-utils \
|
|
dnsutils
|
|
|
|
- name: Install uv
|
|
run: curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
|
|
- name: Install Python dependencies
|
|
run: uv sync
|
|
|
|
- name: Install Ansible collections
|
|
run: uv run ansible-galaxy collection install -r requirements.yml
|
|
|
|
- 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
|
|
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
|
|
local_service_ip: 172.16.0.1
|
|
local_service_ipv6: "fd00::1"
|
|
EOF
|
|
|
|
- name: Run Algo deployment
|
|
run: |
|
|
# Run ansible-playbook via uv - become: true in playbook handles root
|
|
# GitHub runners have passwordless sudo for become escalation
|
|
uv run 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 (service name is strongswan-starter on Ubuntu 20.04+)
|
|
if [[ "${{ matrix.vpn_type }}" == "ipsec" || "${{ matrix.vpn_type }}" == "both" ]]; then
|
|
echo "Checking StrongSwan..."
|
|
sudo ipsec statusall
|
|
if ! sudo systemctl is-active --quiet strongswan-starter; 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
|
|
|
|
# Check dnscrypt-proxy
|
|
if sudo systemctl is-active --quiet dnscrypt-proxy; then
|
|
echo "✓ dnscrypt-proxy is running"
|
|
else
|
|
echo "⚠️ dnscrypt-proxy not running"
|
|
fi
|
|
|
|
# DNS health check - verify DNS resolution works
|
|
echo "Testing DNS resolution via local_service_ip (172.16.0.1)..."
|
|
if dig @172.16.0.1 google.com +short +timeout=5 | grep -q .; then
|
|
echo "✓ DNS resolution working"
|
|
else
|
|
echo "⚠️ DNS resolution failed (service may still be starting)"
|
|
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 (p12 in manual/, mobileconfig in apple/)
|
|
if [[ "${{ matrix.vpn_type }}" == "ipsec" || "${{ matrix.vpn_type }}" == "both" ]]; then
|
|
for user in alice bob; do
|
|
if [ ! -f "configs/localhost/ipsec/manual/${user}.p12" ]; then
|
|
echo "✗ Missing IPsec certificate for ${user}"
|
|
exit 1
|
|
fi
|
|
if [ ! -f "configs/localhost/ipsec/apple/${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: Run E2E VPN connectivity tests
|
|
env:
|
|
VPN_TYPE: ${{ matrix.vpn_type }}
|
|
run: |
|
|
chmod +x tests/e2e/test-vpn-connectivity.sh
|
|
sudo tests/e2e/test-vpn-connectivity.sh "${VPN_TYPE}"
|
|
|
|
- name: Collect E2E debug info on failure
|
|
if: failure()
|
|
run: |
|
|
echo "=== E2E Test Debug Information ==="
|
|
echo "=== Network Namespaces ==="
|
|
ip netns list || true
|
|
echo "=== WireGuard Config (alice) ==="
|
|
cat configs/localhost/wireguard/alice.conf 2>/dev/null || echo "Not found"
|
|
echo "=== IPsec Certificates ==="
|
|
ls -la configs/localhost/ipsec/.pki/certs/ 2>/dev/null || echo "Not found"
|
|
echo "=== iptables NAT ==="
|
|
sudo iptables -t nat -L -n -v || true
|
|
|
|
- name: Upload configs as artifacts
|
|
if: always()
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
with:
|
|
name: vpn-configs-${{ matrix.vpn_type }}-${{ github.run_id }}
|
|
path: configs/
|
|
retention-days: 7
|
|
|
|
- name: Upload logs on failure
|
|
if: failure()
|
|
run: |
|
|
echo "=== Network Interfaces ==="
|
|
ip addr || true
|
|
echo "=== Listening Ports ==="
|
|
sudo ss -tulnp || true
|
|
echo "=== WireGuard Status ==="
|
|
sudo wg show || true
|
|
echo "=== IPsec Status ==="
|
|
sudo ipsec statusall || true
|
|
echo "=== DNS Services ==="
|
|
sudo systemctl status dnscrypt-proxy dnscrypt-proxy.socket dnsmasq --no-pager || true
|
|
echo "=== WireGuard Log ==="
|
|
sudo journalctl -u wg-quick@wg0 -n 50 --no-pager || true
|
|
echo "=== StrongSwan Log ==="
|
|
sudo journalctl -u strongswan -n 50 --no-pager || true
|
|
echo "=== dnscrypt-proxy Log ==="
|
|
sudo journalctl -u dnscrypt-proxy -n 50 --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@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
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"
|