fix(k8s): preserve NAS source IP, production values, pin image digest #32
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: ci | |
| on: | |
| push: | |
| branches: ["main"] | |
| tags: ["v*.*.*"] | |
| pull_request: | |
| branches: ["main"] | |
| workflow_dispatch: | |
| env: | |
| # FreeRADIUS version - must match the version installed in Dockerfile | |
| # Actual version is verified post-build via freeradius -v | |
| IMAGE_VERSION: "3.2.8" | |
| # Docker Hub | |
| DOCKERHUB_REGISTRY: docker.io | |
| DOCKERHUB_IMAGE: cepatkilatteknologi/freeradius | |
| # GitHub Container Registry | |
| GHCR_REGISTRY: ghcr.io | |
| GHCR_IMAGE: ${{ github.repository_owner }}/freeradius | |
| jobs: | |
| # ======================== | |
| # Job 1: Build & Push Docker Image | |
| # ======================== | |
| build-and-push: | |
| name: Build & Push Docker Image | |
| runs-on: ubuntu-latest | |
| environment: ci | |
| permissions: | |
| contents: read | |
| packages: write | |
| id-token: write | |
| attestations: write | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v3 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| # Login to Docker Hub | |
| - name: Log in to Docker Hub | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.DOCKERHUB_REGISTRY }} | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| # Login to GitHub Container Registry | |
| - name: Log in to GitHub Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.GHCR_REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| # Extract metadata for tags | |
| - name: Extract Docker metadata | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: | | |
| ${{ env.DOCKERHUB_REGISTRY }}/${{ env.DOCKERHUB_IMAGE }} | |
| ${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE }} | |
| tags: | | |
| type=raw,value=${{ env.IMAGE_VERSION }} | |
| type=semver,pattern={{version}} | |
| type=semver,pattern={{major}}.{{minor}} | |
| type=sha,prefix= | |
| # Build and push to both registries | |
| - name: Build & Push | |
| id: build-push | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| file: ./Dockerfile | |
| platforms: linux/amd64,linux/arm64 | |
| push: ${{ github.event_name != 'pull_request' }} | |
| provenance: true | |
| sbom: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| # Scan for vulnerabilities | |
| - name: Scan for vulnerabilities | |
| uses: aquasecurity/trivy-action@master | |
| if: ${{ github.event_name != 'pull_request' }} | |
| with: | |
| image-ref: ${{ env.DOCKERHUB_REGISTRY }}/${{ env.DOCKERHUB_IMAGE }}:${{ env.IMAGE_VERSION }} | |
| format: 'sarif' | |
| output: 'trivy-results.sarif' | |
| severity: 'CRITICAL,HIGH' | |
| exit-code: '0' | |
| - name: Upload Trivy scan results | |
| uses: github/codeql-action/upload-sarif@v3 | |
| if: ${{ github.event_name != 'pull_request' }} | |
| with: | |
| sarif_file: 'trivy-results.sarif' | |
| continue-on-error: true | |
| # Detect actual FreeRADIUS version from built image | |
| - name: Detect FreeRADIUS version | |
| if: ${{ github.event_name != 'pull_request' }} | |
| run: | | |
| # Extract version from the amd64 image | |
| VERSION=$(docker run --rm --platform linux/amd64 ${{ env.DOCKERHUB_REGISTRY }}/${{ env.DOCKERHUB_IMAGE }}:${{ env.IMAGE_VERSION }} freeradius -v 2>/dev/null | grep -oP 'FreeRADIUS Version \K[0-9]+\.[0-9]+\.[0-9]+' || echo "${{ env.IMAGE_VERSION }}") | |
| echo "Detected FreeRADIUS version: $VERSION" | |
| if [ "$VERSION" != "${{ env.IMAGE_VERSION }}" ]; then | |
| echo "::warning::IMAGE_VERSION (${{ env.IMAGE_VERSION }}) does not match actual FreeRADIUS version ($VERSION). Update IMAGE_VERSION in ci.yml." | |
| fi | |
| # Generate artifact attestation for Docker Hub | |
| - name: Generate attestation (Docker Hub) | |
| uses: actions/attest-build-provenance@v2 | |
| if: ${{ github.event_name != 'pull_request' }} | |
| with: | |
| subject-name: ${{ env.DOCKERHUB_REGISTRY }}/${{ env.DOCKERHUB_IMAGE }} | |
| subject-digest: ${{ steps.build-push.outputs.digest }} | |
| push-to-registry: true | |
| # Generate artifact attestation for GHCR | |
| - name: Generate attestation (GHCR) | |
| uses: actions/attest-build-provenance@v2 | |
| if: ${{ github.event_name != 'pull_request' }} | |
| with: | |
| subject-name: ${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE }} | |
| subject-digest: ${{ steps.build-push.outputs.digest }} | |
| push-to-registry: true | |
| - name: Summary | |
| if: ${{ github.event_name != 'pull_request' }} | |
| run: | | |
| echo "## Docker Image Published 🐳" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### Images" >> $GITHUB_STEP_SUMMARY | |
| echo "| Registry | Image |" >> $GITHUB_STEP_SUMMARY | |
| echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY | |
| echo "| Docker Hub | \`${{ env.DOCKERHUB_IMAGE }}:${{ env.IMAGE_VERSION }}\` |" >> $GITHUB_STEP_SUMMARY | |
| echo "| GHCR | \`${{ env.GHCR_IMAGE }}:${{ env.IMAGE_VERSION }}\` |" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### Tags" >> $GITHUB_STEP_SUMMARY | |
| echo "\`\`\`" >> $GITHUB_STEP_SUMMARY | |
| echo "${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY | |
| echo "\`\`\`" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Digest:** \`${{ steps.build-push.outputs.digest }}\`" >> $GITHUB_STEP_SUMMARY | |
| # ======================== | |
| # Job 2: Test Docker Image | |
| # ======================== | |
| test: | |
| name: Test Docker Image | |
| runs-on: ubuntu-latest | |
| needs: build-and-push | |
| if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/main' }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Build test image | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| file: ./Dockerfile | |
| load: true | |
| tags: freeradius:test | |
| cache-from: type=gha | |
| - name: Start services | |
| working-directory: examples/docker | |
| run: | | |
| # Create test .env (no leading whitespace) | |
| cat > .env <<EOF | |
| MYSQL_USER=radius | |
| MYSQL_PASSWORD=testpass123 | |
| MYSQL_HOST=db | |
| MYSQL_PORT=3306 | |
| MYSQL_DBNAME=radius | |
| MYSQL_ROOT_PASSWORD=rootpass123 | |
| RADIUS_SECRET=testing123 | |
| HEALTHCHECK_SECRET=testing123 | |
| TZ=UTC | |
| RADIUS_ALLOW_PRIVATE_NETWORKS=true | |
| ACCT_REDIS_ENABLED=false | |
| REDIS_HOST=redis | |
| REDIS_PORT=6379 | |
| REDIS_PASSWORD= | |
| REDIS_DB=0 | |
| EOF | |
| # Strip leading whitespace from .env | |
| sed -i 's/^[[:space:]]*//' .env | |
| # Override image in compose | |
| FREERADIUS_IMAGE=freeradius:test docker compose up -d | |
| - name: Wait for services | |
| working-directory: examples/docker | |
| run: | | |
| echo "Waiting for all services to be healthy..." | |
| for i in $(seq 1 90); do | |
| HEALTHY=$(docker compose ps --format json | grep -c '"healthy"' || true) | |
| TOTAL=$(docker compose ps --format json | wc -l | tr -d ' ') | |
| echo " Healthy: $HEALTHY / $TOTAL ($i/90)" | |
| if [ "$HEALTHY" -ge 3 ] 2>/dev/null; then | |
| echo "All services are healthy!" | |
| break | |
| fi | |
| if [ "$i" -eq 90 ]; then | |
| echo "Timeout waiting for services" | |
| docker compose ps | |
| docker compose logs | |
| exit 1 | |
| fi | |
| sleep 5 | |
| done | |
| docker compose ps | |
| - name: Test RADIUS authentication | |
| working-directory: examples/docker | |
| run: | | |
| # Verify MySQL is actually accepting connections | |
| docker compose exec -T db mysqladmin ping -uroot -prootpass123 --silent | |
| # Add test user | |
| docker compose exec -T db mysql -uroot -prootpass123 radius -e \ | |
| "INSERT INTO radcheck (username, attribute, op, value) VALUES ('testuser', 'Cleartext-Password', ':=', 'testpass') ON DUPLICATE KEY UPDATE value='testpass';" | |
| # Test auth (secret must match clients.conf localhost default) | |
| docker compose exec -T freeradius radtest testuser testpass localhost 0 testing123 | |
| - name: Cleanup | |
| if: always() | |
| working-directory: examples/docker | |
| run: docker compose down -v --remove-orphans |