diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 8c1af14..ca0db1a 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -75,6 +75,39 @@ jobs: - run: echo "SUCCESS!!! 🤩 This job's status is ${{ job.status }}." + test-linux-docker: + runs-on: ubuntu-latest + container: + image: ubuntu:24.04 + options: --privileged + timeout-minutes: 10 + steps: + - uses: actions/checkout@v6 + + - uses: ./ + with: + service-key: ${{ secrets.SERVICE_KEY }} + + - name: Verify Twingate status + run: twingate status + + - name: Access a secure resource + env: + TEST_URL: http://business.prod.beamreachinc.int/ + run: | + curl -v $TEST_URL + + - name: Print client logs + if: always() + run: | + if command -v journalctl >/dev/null 2>&1; then + journalctl -u twingate + elif [ -f /var/log/twingated.log ]; then + cat /var/log/twingated.log + else + echo "No Twingate logs found" + fi + test-windows: strategy: max-parallel: 4 diff --git a/.github/workflows/integration-tests.yaml b/.github/workflows/integration-tests.yaml index 23775b0..6373211 100644 --- a/.github/workflows/integration-tests.yaml +++ b/.github/workflows/integration-tests.yaml @@ -51,6 +51,39 @@ jobs: if: always() run: journalctl -u twingate + test-linux-docker: + runs-on: ubuntu-latest + container: + image: ubuntu:24.04 + options: --privileged + timeout-minutes: 10 + steps: + - name: Test published action + uses: twingate/github-action@main + with: + service-key: ${{ secrets.SERVICE_KEY }} + debug: ${{ inputs.debug || 'false' }} + + - name: Verify Twingate status + run: twingate status + + - name: Access a secure resource + env: + TEST_URL: http://business.prod.beamreachinc.int/ + run: | + curl -v $TEST_URL + + - name: Print client logs + if: always() + run: | + if command -v journalctl >/dev/null 2>&1; then + journalctl -u twingate + elif [ -f /var/log/twingated.log ]; then + cat /var/log/twingated.log + else + echo "No Twingate logs found" + fi + test-windows: strategy: max-parallel: 4 diff --git a/action.yml b/action.yml index 2d806dd..97afcd8 100644 --- a/action.yml +++ b/action.yml @@ -26,17 +26,35 @@ runs: if: runner.os != 'Linux' && runner.os != 'Windows' shell: bash run: | - source ${{ github.action_path }}/scripts/linux-helpers.sh + source "$GITHUB_ACTION_PATH/scripts/linux-helpers.sh" log ERROR "Unsupported Runner OS: ${{ runner.os }}" exit 1 + - name: Install prerequisites (Linux) + if: runner.os == 'Linux' + shell: bash + run: | + # Check if we're in a minimal container environment missing required tools + MISSING_DEPS="" + command -v curl >/dev/null 2>&1 || MISSING_DEPS="$MISSING_DEPS curl" + command -v gpg >/dev/null 2>&1 || MISSING_DEPS="$MISSING_DEPS gnupg" + + if [ -n "$MISSING_DEPS" ]; then + # Detect if we need sudo for package installation + source "$GITHUB_ACTION_PATH/scripts/sudo-detect.sh" + + echo "Installing missing dependencies: $MISSING_DEPS" + $SUDO apt-get update + $SUDO apt-get install -y $MISSING_DEPS + fi + - name: Get latest Twingate version (Linux) if: runner.os == 'Linux' && inputs.cache == 'true' id: twingate-version-linux shell: bash run: | export DEBUG_MODE='${{ inputs.debug }}' - source ${{ github.action_path }}/scripts/linux-helpers.sh + source "$GITHUB_ACTION_PATH/scripts/linux-helpers.sh" VERSION=$(get_twingate_version) echo "version=$VERSION" >> $GITHUB_OUTPUT @@ -50,7 +68,7 @@ runs: shell: powershell run: | $env:DEBUG_MODE = '${{ inputs.debug }}' - . ${{ github.action_path }}/scripts/windows-helpers.ps1 + . "$env:GITHUB_ACTION_PATH/scripts/windows-helpers.ps1" $version = Get-TwingateVersion Add-Content -Path $env:GITHUB_OUTPUT -Value "version=$version" @@ -95,7 +113,7 @@ runs: shell: bash run: | export DEBUG_MODE='${{ inputs.debug }}' - source ${{ github.action_path }}/scripts/linux-helpers.sh + source "$GITHUB_ACTION_PATH/scripts/linux-helpers.sh" VALID=$(validate_cache_linux) echo "valid=$VALID" >> $GITHUB_OUTPUT @@ -106,7 +124,7 @@ runs: shell: powershell run: | $env:DEBUG_MODE = '${{ inputs.debug }}' - . ${{ github.action_path }}/scripts/windows-helpers.ps1 + . "$env:GITHUB_ACTION_PATH/scripts/windows-helpers.ps1" $cacheDir = "${{ runner.temp }}\twingate-cache" $isValid = Validate-CacheWindows -CacheDir $cacheDir @@ -117,19 +135,19 @@ runs: shell: bash run: | export DEBUG_MODE='${{ inputs.debug }}' - source ${{ github.action_path }}/scripts/linux-helpers.sh + source "$GITHUB_ACTION_PATH/scripts/linux-helpers.sh" log DEBUG "Installing Twingate from cache" # Install all packages from cache directory (twingate + dependencies) - sudo dpkg -i ~/.twingate-cache/*.deb || true - sudo apt-get install -f -yq + $SUDO dpkg -i ~/.twingate-cache/*.deb || true + $SUDO apt-get install -f -yq - name: Copy cached MSI to working directory (Windows) if: runner.os == 'Windows' && inputs.cache == 'true' && steps.validate-cache-windows.outputs.valid == 'true' shell: powershell run: | $env:DEBUG_MODE = '${{ inputs.debug }}' - . ${{ github.action_path }}/scripts/windows-helpers.ps1 + . "$env:GITHUB_ACTION_PATH/scripts/windows-helpers.ps1" log DEBUG "Copying cached MSI to working directory" $cacheDir = "${{ runner.temp }}\twingate-cache" @@ -147,34 +165,36 @@ runs: if: runner.os == 'Linux' && (inputs.cache != 'true' || steps.cache-twingate-linux.outputs.cache-hit != 'true' || steps.validate-cache-linux.outputs.valid != 'true' || steps.twingate-version-linux.outputs.version == 'unknown') shell: bash run: | + source "$GITHUB_ACTION_PATH/scripts/linux-helpers.sh" + # Import Twingate GPG key for signature verification - curl -fsSL https://packages.twingate.com/apt/gpg.key | sudo gpg --batch --yes --no-tty --dearmor -o /usr/share/keyrings/twingate-client-keyring.gpg + curl -fsSL https://packages.twingate.com/apt/gpg.key | $SUDO gpg --batch --yes --no-tty --dearmor -o /usr/share/keyrings/twingate-client-keyring.gpg # Add Twingate repository with GPG key verification - echo "deb [signed-by=/usr/share/keyrings/twingate-client-keyring.gpg] https://packages.twingate.com/apt/ * *" | sudo tee /etc/apt/sources.list.d/twingate.list + echo "deb [signed-by=/usr/share/keyrings/twingate-client-keyring.gpg] https://packages.twingate.com/apt/ * *" | $SUDO tee /etc/apt/sources.list.d/twingate.list - sudo apt update - sudo apt-get update -o Dir::Etc::sourcelist="sources.list.d/twingate.list" -o Dir::Etc::sourceparts="-" -o APT::Get::List-Cleanup="0" + $SUDO apt update + $SUDO apt-get update -o Dir::Etc::sourcelist="sources.list.d/twingate.list" -o Dir::Etc::sourceparts="-" -o APT::Get::List-Cleanup="0" # Download all packages to cache if caching is enabled if [ "${{ steps.twingate-version-linux.outputs.version }}" != "unknown" ]; then mkdir -p ~/.twingate-cache # Download Twingate and all dependencies to cache directory - sudo apt-get install -yq --download-only -o Dir::Cache::Archives="$HOME/.twingate-cache" twingate + $SUDO apt-get install -yq --download-only -o Dir::Cache::Archives="$HOME/.twingate-cache" twingate # Install to resolve any missing dependencies, then download them - sudo apt-get install -yq --download-only -o Dir::Cache::Archives="$HOME/.twingate-cache" -f + $SUDO apt-get install -yq --download-only -o Dir::Cache::Archives="$HOME/.twingate-cache" -f # Fix permissions so cache action can save files - sudo chown -R "$(id -u)":"$(id -g)" "$HOME/.twingate-cache" + $SUDO chown -R "$(id -u)":"$(id -g)" "$HOME/.twingate-cache" fi - sudo apt install -yq twingate + $SUDO apt install -yq twingate - name: Download and cache Twingate MSI (Windows) if: runner.os == 'Windows' && (inputs.cache != 'true' || steps.cache-twingate-windows.outputs.cache-hit != 'true' || steps.validate-cache-windows.outputs.valid != 'true' || steps.twingate-version-windows.outputs.version == 'unknown') shell: powershell run: | $env:DEBUG_MODE = '${{ inputs.debug }}' - . ${{ github.action_path }}/scripts/windows-helpers.ps1 + . "$env:GITHUB_ACTION_PATH/scripts/windows-helpers.ps1" # Download MSI $msiUrl = "https://api.twingate.com/download/windows?installer=msi" @@ -200,9 +220,9 @@ runs: shell: bash run: | export DEBUG_MODE='${{ inputs.debug }}' - source ${{ github.action_path }}/scripts/linux-helpers.sh + source "$GITHUB_ACTION_PATH/scripts/linux-helpers.sh" - echo '${{ inputs.service-key }}' | sudo twingate setup --headless - + echo '${{ inputs.service-key }}' | $SUDO twingate setup --headless - MAX_RETRIES=5 WAIT_TIME=5 n=0 @@ -248,7 +268,7 @@ runs: shell: powershell run: | $env:DEBUG_MODE = '${{ inputs.debug }}' - . ${{ github.action_path }}/scripts/windows-helpers.ps1 + . "$env:GITHUB_ACTION_PATH/scripts/windows-helpers.ps1" # Install Twingate client and start service Set-Content .\key.json '${{ inputs.service-key }}' diff --git a/scripts/linux-helpers.sh b/scripts/linux-helpers.sh index 27cb719..09ec63c 100644 --- a/scripts/linux-helpers.sh +++ b/scripts/linux-helpers.sh @@ -2,6 +2,9 @@ # Linux helper functions for logging, version detection, and cache validation # Usage: source ./scripts/linux-helpers.sh +# Source SUDO detection +source "$(dirname "${BASH_SOURCE[0]}")/sudo-detect.sh" + log() { local level=$1 shift diff --git a/scripts/sudo-detect.sh b/scripts/sudo-detect.sh new file mode 100755 index 0000000..86f993f --- /dev/null +++ b/scripts/sudo-detect.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# Detects and sets SUDO variable for privilege escalation +# Usage: source sudo-detect.sh + +if [ "$(id -u)" -eq 0 ]; then + SUDO="" +else + if command -v sudo >/dev/null 2>&1; then + SUDO="sudo" + else + echo "[ERROR] sudo is not available. Please run this script as root." >&2 + exit 1 + fi +fi + +export SUDO