image: atlassian/default-image:3

definitions:
  steps:
    - step: &install-dependencies
        name: Install Dependencies
        script:
          - apt-get update && apt-get install -y git python3-pip curl unzip wget default-jdk jq
          - python3 --version
          - echo "Installing pip..."
          - curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
          - python3 get-pip.py
          - export PATH="/root/.local/bin:$PATH"
          - pip --version
          - echo "Installing Selenium..."
          - pip install selenium bandit safety
          #- python3 -c "import selenium; print(Selenium version: selenium.__version__)"
    - step: &run-sonarqube
        name: SonarQube analysis
        script:
          - pipe: sonarsource/sonarqube-scan:2.0.1
            variables:
              SONAR_HOST_URL: ${SONAR_HOST_URL}
              SONAR_TOKEN: ${SONAR_TOKEN}
          - echo "Extracting SonarQube results..."
          - curl -u "${SONAR_TOKEN}:" "${SONAR_HOST_URL}/api/qualitygates/project_status?projectKey=${BITBUCKET_REPO_SLUG}" > sonar_results.txt
        artifacts:
          - sonar_results.txt
    - step: &run-bandit
        name: Run Bandit
        script:
          - bandit -r . -f custom --msg-template "{abspath}:{line}:{severity}:{test_id}:{msg}" > bandit_results.txt

    - step: &run-safety
        name: Run Safety
        script:
          - |
            if [ -f requirements.txt ]; then
              safety check -r requirements.txt > safety_results.txt
            else
              echo "No requirements.txt found. Skipping Safety check." > safety_results.txt
            fi

    - step: &run-gitleaks
        name: Run Gitleaks
        script:
          - curl -sL https://github.com/zricethezav/gitleaks/releases/download/v8.15.3/gitleaks_8.15.3_linux_x64.tar.gz | tar xz
          - ./gitleaks detect --source . -v > gitleaks_results.txt || echo "Gitleaks found potential secrets. Check gitleaks_results.txt for details."

    - step: &run-dependency-check
        name: Run OWASP Dependency-Check
        script:
          - |
            DC_VERSION="7.4.4"
            curl -sL https://github.com/jeremylong/DependencyCheck/releases/download/v$DC_VERSION/dependency-check-$DC_VERSION-release.zip -o dc.zip
            unzip -q dc.zip && rm dc.zip
            ./dependency-check/bin/dependency-check.sh --scan . --format "HTML" --out dependency-check-report.html

    - step: &run-selenium-tests
        name: Run Selenium Tests
        script:
          - |
            # Install ChromeDriver
            CHROME_DRIVER_VERSION=$(curl -sS https://chromedriver.storage.googleapis.com/LATEST_RELEASE)
            curl -sS -o /tmp/chromedriver.zip https://chromedriver.storage.googleapis.com/$CHROME_DRIVER_VERSION/chromedriver_linux64.zip
            unzip -o /tmp/chromedriver.zip -d /usr/local/bin/
            chmod +x /usr/local/bin/chromedriver

            # Check if Selenium is installed
            echo "Checking if Selenium is installed..."
            python3 -m pip show selenium || (echo "Selenium is not installed, attempting to install..." && pip3 install selenium)

            # Verify Selenium installation
            python3 -c "import selenium; print(f'Selenium version: {selenium.__version__}')"

            echo "Running Selenium tests..." > selenium_results.txt
            if [ -d "tests/selenium" ]; then
              for side_file in tests/selenium/*.side; do
                if [ -f "$side_file" ]; then
                  echo "Running tests from $side_file" >> selenium_results.txt
                  python3 -m selenium.webdriver.chrome.service --executable-path=/usr/local/bin/chromedriver
                  if python3 -m selenium.webdriver.support.event_firing_webdriver --url $APPLICATION_URL --side-file "$side_file" >> selenium_results.txt 2>&1; then
                    echo "Tests in $side_file completed successfully" >> selenium_results.txt
                  else
                    echo "Tests in $side_file failed or encountered an error" >> selenium_results.txt
                  fi
                  echo "" >> selenium_results.txt
                fi
              done
            else
              echo "Directory tests/selenium not found. Skipping Selenium tests." >> selenium_results.txt
            fi

    - step: &prepare-results
        name: Prepare Scan Results
        script:
          - |
            echo "Preparing scan results..."
            BANDIT_RESULTS=$(cat bandit_results.txt | jq -Rs .)
            SAFETY_RESULTS=$(cat safety_results.txt | jq -Rs .)
            GITLEAKS_RESULTS=$(cat gitleaks_results.txt | jq -Rs .)
            if [ -f zap-report.html ]; then
              ZAP_RESULTS=$(grep -A 5 "Alerts Summary" zap-report.html | jq -Rs .)
            else
              ZAP_RESULTS=$(echo "ZAP scan did not produce a report" | jq -Rs .)
            fi
            SELENIUM_RESULTS=$(cat selenium_results.txt | jq -Rs .)

    - step: &send-to-supabase
        name: Send Results to Supabase
        script:
          - |
            echo "Entering scan results into Supabase..."
            CURRENT_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
            curl -X POST 'https://supabase.appmonitor.co.za/rest/v1/deploy_results' \
              -H "apikey: $SUPABASE_API_KEY" \
              -H "Authorization: Bearer $SUPABASE_API_KEY" \
              -H "Content-Type: application/json" \
              -H "Prefer: return=minimal" \
              -d '{
                "repo_name": "'"$BITBUCKET_REPO_SLUG"'",
                "repo_owner": "'"$BITBUCKET_REPO_OWNER"'",
                "commit_hash": "'"$BITBUCKET_COMMIT"'",
                "build_number": "'"$BITBUCKET_BUILD_NUMBER"'",
                "scan_date": "'"$CURRENT_DATE"'",
                "bandit_results": '"$BANDIT_RESULTS"',
                "safety_results": '"$SAFETY_RESULTS"',
                "gitleaks_results": '"$GITLEAKS_RESULTS"',
                "zap_results": '"$ZAP_RESULTS"',
                "selenium_results": '"$SELENIUM_RESULTS"',
                "sonar_results": '"$SONAR_RESULTS"'
              }'

    - step: &send-email
        name: Send Email Notification
        script:
          - |
            echo "Sending security scan results via email..."
            SUBJECT="Security Scan Results for $BITBUCKET_REPO_SLUG (Commit: ${BITBUCKET_COMMIT:0:7})"
            BODY="Please find attached the security scan results for $BITBUCKET_REPO_SLUG (Build #$BITBUCKET_BUILD_NUMBER, Commit: ${BITBUCKET_COMMIT:0:7})."
            ATTACHMENT_CONTENT=$(base64 scan_results.txt)
            curl -X POST https://api.resend.com/emails \
              -H "Authorization: Bearer $RESEND_API_KEY" \
              -H "Content-Type: application/json" \
              -d '{
                "from": "Security Scanner <security-scanner@yourdomain.com>",
                "to": "'"$EMAIL_RECIPIENT"'",
                "subject": "'"$SUBJECT"'",
                "text": "'"$BODY"'",
                "attachments": [
                  {
                    "filename": "scan_results.txt",
                    "content": "'"$ATTACHMENT_CONTENT"'"
                  }
                ]
              }'

    - step: &post-to-slack
        name: Post Results to Slack
        script:
          - |
            curl -X POST -H 'Content-type: application/json' --data '{
              "text": "Security Scan Results for '"$BITBUCKET_REPO_SLUG"' (Commit: '"${BITBUCKET_COMMIT:0:7}"')",
              "attachments": [
                {
                  "color": "#36a64f",
                  "title": "Security Scan Completed",
                  "text": "'"$(cat scan_results.txt | sed 's/"/\\"/g')"'",
                  "footer": "Bitbucket Pipeline | Build #'"$BITBUCKET_BUILD_NUMBER"' | Commit '"${BITBUCKET_COMMIT:0:7}"'"
                }
              ]
            }' $SLACK_WEBHOOK_URL

    - step: &deploy
        name: Deploy and Invalidate Cache
        oidc: true
        deployment: Production
        script:
          - echo "Deploying to S3..."
          - pipe: atlassian/aws-s3-deploy:1.1.0
            variables:
              AWS_OIDC_ROLE_ARN: $AWS_ARN
              AWS_DEFAULT_REGION: $AWS_REGION
              S3_BUCKET: $AWS_S3_BUCKET
              LOCAL_PATH: './build/web'
          - echo "Invalidating Cloudfront Cache..."
          - pipe: atlassian/aws-cloudfront-invalidate:0.10.1
            variables:
              AWS_OIDC_ROLE_ARN: $AWS_ARN
              AWS_DEFAULT_REGION: $AWS_REGION
              DISTRIBUTION_ID: $DISTRIBUTION_ID

pipelines:
  default:
    #- step: *install-dependencies
    - step: *run-sonarqube
    # - step: *run-bandit
    #- step: *run-safety
    #- step: *run-gitleaks
    #- step: *run-dependency-check
    #- step: *run-selenium-tests
    #- step: *prepare-results
    #- step: *send-to-supabase
    # - step: *send-email
    # - step: *post-to-slack

  branches:
    main:
      #- step: *install-dependencies
      - step: *run-sonarqube
      #- step: *run-bandit
      #- step: *run-safety
      #- step: *run-gitleaks
      #- step: *run-dependency-check
      #- step: *run-selenium-tests
      #- step: *prepare-results
      #- step: *send-to-supabase
      # - step: *send-email
      # - step: *post-to-slack
      #- step: *deploy

  pull-requests:
    '**':
      - step: *install-dependencies
      - step: *run-sonarqube
      # - step: *run-bandit
      - step: *run-safety
      - step: *run-gitleaks
      - step: *run-dependency-check
      - step: *run-selenium-tests
      - step: *prepare-results
      - step: *send-to-supabase
      # - step: *send-email
      # - step: *post-to-slack

  custom:
    manual-security-scan:
      - step: *install-dependencies
      - step: *run-sonarqube
      # - step: *run-bandit
      - step: *run-safety
      - step: *run-gitleaks
      - step: *run-dependency-check
      - step: *run-selenium-tests
      - step: *prepare-results
      - step: *send-to-supabase
      # - step: *send-email
      # - step: *post-to-slack