name: "security"

permissions:
  actions: read
  contents: read
  security-events: write

on:
  workflow_dispatch:

  # Uncomment when testing.
  # pull_request:

  schedule:
    # Run every 6 hours Monday-Friday!
    - cron: "0 0/6 * * 1-5"

# Cancel in-progress runs for pull requests when developers push
# additional changes
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}-security
  cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
  codeql:
    runs-on: ${{ github.repository_owner == 'coder' && 'buildjet-8vcpu-ubuntu-2204' || 'ubuntu-latest' }}
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Initialize CodeQL
        uses: github/codeql-action/init@v2
        with:
          languages: go, javascript

      - name: Setup Go
        uses: ./.github/actions/setup-go

      # Workaround to prevent CodeQL from building the dashboard.
      - name: Remove Makefile
        run: |
          rm Makefile

      - name: Perform CodeQL Analysis
        uses: github/codeql-action/analyze@v2

      - name: Send Slack notification on failure
        if: ${{ failure() }}
        run: |
          msg="❌ CodeQL Failed\n\nhttps://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
          curl \
            -qfsSL \
            -X POST \
            -H "Content-Type: application/json" \
            --data "{\"content\": \"$msg\"}" \
            "${{ secrets.SLACK_SECURITY_FAILURE_WEBHOOK_URL }}"

  trivy:
    runs-on: ${{ github.repository_owner == 'coder' && 'buildjet-8vcpu-ubuntu-2204' || 'ubuntu-latest' }}
    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          fetch-depth: 0

      - name: Setup Go
        uses: ./.github/actions/setup-go

      - name: Setup Node
        uses: ./.github/actions/setup-node

      - name: Setup sqlc
        uses: ./.github/actions/setup-sqlc

      - name: Install yq
        run: go run github.com/mikefarah/yq/v4@v4.30.6
      - name: Install mockgen
        run: go install github.com/golang/mock/mockgen@v1.6.0
      - name: Install protoc-gen-go
        run: go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.30
      - name: Install protoc-gen-go-drpc
        run: go install storj.io/drpc/cmd/protoc-gen-go-drpc@v0.0.33
      - name: Install Protoc
        run: |
          # protoc must be in lockstep with our dogfood Dockerfile or the
          # version in the comments will differ. This is also defined in
          # ci.yaml.
          set -x
          cd dogfood
          DOCKER_BUILDKIT=1 docker build . --target proto -t protoc
          protoc_path=/usr/local/bin/protoc
          docker run --rm --entrypoint cat protoc /tmp/bin/protoc > $protoc_path
          chmod +x $protoc_path
          protoc --version

      - name: Build Coder linux amd64 Docker image
        id: build
        run: |
          set -euo pipefail

          version="$(./scripts/version.sh)"
          image_job="build/coder_${version}_linux_amd64.tag"

          # This environment variable force make to not build packages and
          # archives (which the Docker image depends on due to technical reasons
          # related to concurrent FS writes).
          export DOCKER_IMAGE_NO_PREREQUISITES=true
          # This environment variables forces scripts/build_docker.sh to build
          # the base image tag locally instead of using the cached version from
          # the registry.
          export CODER_IMAGE_BUILD_BASE_TAG="$(CODER_IMAGE_BASE=coder-base ./scripts/image_tag.sh --version "$version")"

          make -j "$image_job"
          echo "image=$(cat "$image_job")" >> $GITHUB_OUTPUT

      - name: Run Prisma Cloud image scan
        uses: PaloAltoNetworks/prisma-cloud-scan@v1
        with:
          pcc_console_url: ${{ secrets.PRISMA_CLOUD_URL }}
          pcc_user: ${{ secrets.PRISMA_CLOUD_ACCESS_KEY }}
          pcc_pass: ${{ secrets.PRISMA_CLOUD_SECRET_KEY }}
          image_name: ${{ steps.build.outputs.image }}

      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@fbd16365eb88e12433951383f5e99bd901fc618f
        with:
          image-ref: ${{ steps.build.outputs.image }}
          format: sarif
          output: trivy-results.sarif
          severity: "CRITICAL,HIGH"

      - name: Upload Trivy scan results to GitHub Security tab
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: trivy-results.sarif
          category: "Trivy"

      - name: Upload Trivy scan results as an artifact
        uses: actions/upload-artifact@v3
        with:
          name: trivy
          path: trivy-results.sarif
          retention-days: 7

      - name: Send Slack notification on failure
        if: ${{ failure() }}
        run: |
          msg="❌ Trivy Failed\n\nhttps://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
          curl \
            -qfsSL \
            -X POST \
            -H "Content-Type: application/json" \
            --data "{\"content\": \"$msg\"}" \
            "${{ secrets.SLACK_SECURITY_FAILURE_WEBHOOK_URL }}"
