diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..c62d3bc --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,33 @@ +name: Dry run + +on: + pull_request: + branches: [ "main" ] + +jobs: + dry-run: + runs-on: ubuntu-22.04 + + steps: + - uses: actions/checkout@v3 + + - name: Run setup script and sanity testing using incoming PR + run: bash .github/workflows/scripts/dry-run.sh + + end-to-end-testing: + runs-on: ubuntu-22.04 + environment: dev + env: + OCI_API_KEY_PRIV: ${{ secrets.OCI_API_KEY_PRIV }} + OCI_API_KEY_PUB: ${{ secrets.OCI_API_KEY_PUB }} + OCI_CID: ${{ secrets.OCI_CID }} + OCI_COMP_ID: ${{ secrets.OCI_COMP_ID }} + OCI_SUBNET_ID: ${{ secrets.OCI_SUBNET_ID }} + OCI_AVAILABILITY_DOMAIN: ${{ secrets.OCI_AVAILABILITY_DOMAIN }} + OCI_SHAPE: ${{ secrets.OCI_SHAPE }} + OCI_IMAGE_ID: ${{ secrets.OCI_IMAGE_ID }} + steps: + - uses: actions/checkout@v3 + + - name: Run end-to-end testing using incoming PR + run: bash .github/workflows/scripts/end-to-end.sh diff --git a/.github/workflows/dry-run.yml b/.github/workflows/dry-run.yml deleted file mode 100644 index 4f83e18..0000000 --- a/.github/workflows/dry-run.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Dry run - -on: - pull_request: - branches: [ "main" ] - -jobs: - install-and-run: - runs-on: ubuntu-22.04 - - steps: - - uses: actions/checkout@v3 - - - name: Run setup script from PR - run: | - chmod +x .github/workflows/scripts/dry-run.sh - .github/workflows/scripts/dry-run.sh diff --git a/.github/workflows/scripts/end-to-end.sh b/.github/workflows/scripts/end-to-end.sh new file mode 100644 index 0000000..77cee76 --- /dev/null +++ b/.github/workflows/scripts/end-to-end.sh @@ -0,0 +1,78 @@ +set -e + +echo "Starting end-to-end" + +cleanup() { + rm -f \ + client_privatekey \ + client_publickey \ + oci-install.sh \ + wg-client.conf +} +trap cleanup EXIT + +sudo apt update +sudo apt install -y \ + wireguard \ + jq + +# Generate SSH key +KEY_NAME="test-$(date +%s%N | md5sum | head -c 8)" +SSH_KEY="$HOME/.ssh/$KEY_NAME" +ssh-keygen -t rsa -b 4096 -f "$SSH_KEY" -N "" + +# Generate client WireGuard keys +if ! wg genkey | tee client_privatekey | wg pubkey | tee client_publickey; then + echo "Failed to generate WireGuard keys" + exit 1 +fi +WG_CLIENT_PUBKEY=$(cat client_publickey) + +# Download OCI binary +curl -L https://raw.githubusercontent.com/oracle/oci-cli/master/scripts/install/install.sh > oci-install.sh +chmod +x oci-install.sh +./oci-install.sh --accept-all-defaults +OCI=~/bin/oci +mkdir ~/.oci +echo "$OCI_API_KEY_PRIV" > ~/.oci/oci_api_key.pem +echo "$OCI_API_KEY_PUB" > ~/.oci/oci_api_key_public.pem +chmod 600 ~/.oci/oci_api_key.pem ~/.oci/oci_api_key_public.pem + +# Start instance in OCI +SERVER_IP=$(bash .github/workflows/scripts/start-instance.sh $SSH_KEY) +if [ -z "$SERVER_IP" ]; then + echo "Failed to get server IP" + exit 1 +fi + +# TODO: Open port for instance +echo "Waiting for instance to be ready..." +sleep 30 + +# Install WireGuard in OCI instance +sed -i "s/CLIENT_PUBLIC_KEY_PLACEHOLDER/$WG_CLIENT_PUBKEY/" .github/workers/scripts/setup-vpn.sh +scp -o StrictHostKeyChecking=accept-new -i "$SSH_KEY" .github/workers/scripts/setup-vpn.sh ubuntu@$SERVER_IP:/tmp +SERVER_PUBLIC_KEY=$(ssh -o StrictHostKeyChecking=accept-new -i "$SSH_KEY" ubuntu@$SERVER_IP "bash /tmp/setup-vpn.sh") +if [ -z "$SERVER_PUBLIC_KEY" ]; then + echo "Failed to get server public key" + exit 1 +fi + +# Create client config +tee wg-client.conf << EOF +[Interface] +PrivateKey = $(cat client_privatekey) +Address = 10.0.0.2/24 + +[Peer] +PublicKey = $SERVER_PUBLIC_KEY +Endpoint = $SERVER_IP:51820 +AllowedIPs = 10.0.0.0/24 +PersistentKeepalive = 25 +EOF + +# Connect to VPN +if ! sudo wg-quick up wg-client.conf; then + echo "Failed to establish WireGuard connection" + exit 1 +fi diff --git a/.github/workflows/scripts/setup-vpn.sh b/.github/workflows/scripts/setup-vpn.sh new file mode 100644 index 0000000..81ca200 --- /dev/null +++ b/.github/workflows/scripts/setup-vpn.sh @@ -0,0 +1,33 @@ +set -e + +sudo apt update +sudo apt install -y wireguard + +# Generate server keys +cd /etc/wireguard +umask 077 +if ! wg genkey | sudo tee privatekey | wg pubkey | sudo tee publickey; then + echo "Failed to generate WireGuard keys" >&2 + exit 1 +fi + +# Create server config +sudo tee /etc/wireguard/wg0.conf << EOF +[Interface] +PrivateKey = $(cat privatekey) +Address = 10.0.0.1/24 +ListenPort = 51820 +SaveConfig = false + +[Peer] +PublicKey = CLIENT_PUBLIC_KEY_PLACEHOLDER +AllowedIPs = 10.0.0.2/32 +EOF + +# Start WireGuard and enable on boot +if ! sudo systemctl enable --now wg-quick@wg0; then + echo "Failed to start WireGuard service" >&2 + exit 1 +fi + +echo "$(cat publickey)" diff --git a/.github/workflows/scripts/start-instance.sh b/.github/workflows/scripts/start-instance.sh new file mode 100644 index 0000000..91e61f2 --- /dev/null +++ b/.github/workflows/scripts/start-instance.sh @@ -0,0 +1,42 @@ +set -e + +OCI=~/bin/oci +SSH_KEY=$1 + +#OCI_CID +#OCI_COMP_ID +#OCI_SUBNET_ID +#OCI_AVAILABILITY_DOMAIN +#OCI_SHAPE +#OCI_IMAGE_ID + +VM_CREATE_RESULT=$($OCI compute instance launch \ + --compartment-id "$OCI_COMP_ID" \ + --shape "$OCI_SHAPE" \ + --subnet-id "$OCI_SUBNET_ID" \ + --availability-domain "$OCI_AVAILABILITY_DOMAIN" \ + --source-details "{\"sourceType\": \"image\", \"imageId\": \"$OCI_IMAGE_ID\"}" \ + --metadata "{\"ssh_authorized_keys\": \"$(cat $SSH_KEY)\"}") +echo "VM creation result: $VM_CREATE_RESULT" + +if echo "$VM_CREATE_RESULT" | jq -e '.data.id' >/dev/null 2>&1; then + INSTANCE_ID=$(echo "$VM_CREATE_RESULT" | jq -r '.data.id') + echo "Successfully created instance with ID: $INSTANCE_ID" +else + echo "Error: Failed to create instance or get instance ID" + echo "Response did not contain expected data structure" + exit 1 +fi + +GET_VNIC_RESULT=$($OCI compute instance list-vnics --instance-id "$INSTANCE_ID") +echo "Get VNIC result: $GET_VNIC_RESULT" +if echo "$GET_VNIC_RESULT" | jq -e '.data[0]."public-ip"' >/dev/null 2>&1; then + PUBLIC_IP=$(echo "$GET_VNIC_RESULT" | jq -r '.data[0]."public-ip"') + echo "Successfully retrieved public IP: $PUBLIC_IP" +else + echo "Error: Failed to get public IP" + echo "Response did not contain expected VNIC data" + exit 1 +fi + +echo $PUBLIC_IP