diff --git a/config/examples/3rd-party-sec-scan-config.yaml b/config/examples/3rd-party-sec-scan-config.yaml new file mode 100644 index 00000000..e1eafb38 --- /dev/null +++ b/config/examples/3rd-party-sec-scan-config.yaml @@ -0,0 +1,52 @@ +--- + +qubership-jaeger: + - envoyproxy/envoy:v1.35.2 + - ghcr.io/jaegertracing/spark-dependencies/spark-dependencies:latest + - jaegertracing/example-hotrod:1.74.0 + # - jaegertracing/jaeger:2.11.0 + # - jaegertracing/jaeger-cassandra-schema:1.74.0 + # - jaegertracing/jaeger-es-index-cleaner:1.74.0 + # - jaegertracing/jaeger-es-rollover:1.74.0 +qubership-logging-operator: + - docker.io/alpine:3.21.3 + - docker.io/fluent/fluent-bit:4.0.1 + # - docker.io/graylog/graylog:5.2.12 + # - docker.io/mongo:5.0.31 + # - fluent/fluent-bit:3.0.6 + # - ghcr.io/jimmidyson/configmap-reload:v0.13.1 + # - ghcr.io/jimmidyson/configmap-reload:v0.15.0 + # - graylog/graylog:5.2.7 + # - mongo:5.0.19 +qubership-monitoring-operator: + - docker.io/bloomberg/goldpinger:3.10.2 + - docker.io/grafana/grafana:11.6.5 + # - docker.io/grafana/grafana-image-renderer:3.12.9 + # - docker.io/jimmidyson/configmap-reload:v0.5.0 + # - docker.io/joeelliott/cert-exporter:v2.14.0 + # - docker.io/prom/alertmanager:v0.28.1 + # - docker.io/prom/blackbox-exporter:v0.27.0 + # - docker.io/prom/cloudwatch-exporter:v0.16.0 + # - docker.io/prom/node-exporter:v1.9.0 + # - docker.io/prom/prometheus:v3.2.1 + # - docker.io/prom/pushgateway:v1.11.0 + # - docker.io/prometheuscommunity/json-exporter:v0.7.0 + # - docker.io/prometheuscommunity/stackdriver-exporter:v0.18.0 + # - docker.io/victoriametrics/operator:config-reloader-v0.63.0 + # - docker.io/victoriametrics/operator:v0.63.0 + # - docker.io/victoriametrics/victoria-metrics:v1.126.0 + # - docker.io/victoriametrics/vmagent:v1.126.0 + # - docker.io/victoriametrics/vmalert:v1.126.0 + # - docker.io/victoriametrics/vmauth:v1.126.0 + # - docker.io/victoriametrics/vminsert:v1.126.0-cluster + # - docker.io/victoriametrics/vmselect:v1.126.0-cluster + # - docker.io/victoriametrics/vmstorage:v1.126.0-cluster + # - gcr.io/stackdriver-prometheus/stackdriver-prometheus-sidecar:0.8.0 + # - ghcr.io/jimmidyson/configmap-reload:v0.14.0 + # - ghcr.io/tomkerkhove/promitor-agent-resource-discovery:0.13.0 + # - ghcr.io/tomkerkhove/promitor-agent-scraper:2.13.0 + # - quay.io/grafana-operator/grafana-operator:v4.9.0 + # - quay.io/jacksontj/promxy:v0.0.92 + # - quay.io/prometheus-operator/prometheus-config-reloader:v0.80.1 + # - quay.io/prometheus-operator/prometheus-operator:v0.80.1 + # - registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.15.0 diff --git a/workflow-templates/3rd-party-sec-scan.yaml b/workflow-templates/3rd-party-sec-scan.yaml new file mode 100644 index 00000000..938b20e8 --- /dev/null +++ b/workflow-templates/3rd-party-sec-scan.yaml @@ -0,0 +1,178 @@ +--- + +# Workflow to scan Docker images vulnerabilities by Grape and Trivy +# To make it work create a configuration file .qubership/3rd-party-sec-scan-config.yaml +# Example configuration file can be found there: config/examples/3rd-party-sec-scan-config.yaml +name: Security Scan Docker images +run-name: > + Security Scan +on: + workflow_dispatch: + inputs: + only-high-critical: + description: "Scope only HIGH + CRITICAL" + required: false + default: true + type: boolean + trivy-scan: + description: "Trivy scan" + required: false + default: true + type: boolean + grype-scan: + description: "Grype scan" + required: false + default: true + type: boolean + continue-on-error: + description: "Continue on error" + required: false + default: true + type: boolean + only-fixed: + description: "Ignore unfixed vulnerabilities" + required: false + default: true + type: boolean + schedule: + - cron: "0 3 * * 0" # every Sunday at 03:00 UTC +permissions: + contents: read + +env: + CONFIG_FILE: .qubership/3rd-party-sec-scan-config.yaml + REPORT_BRANCH: reports +jobs: + load-config: + runs-on: ubuntu-latest + outputs: + packages: ${{ steps.config.outputs.packages }} + steps: + - name: Checkout + uses: actions/checkout@v5 + - name: Read config + id: config + run: | + echo "only-high-critical: ${{ inputs.only-high-critical }}" + echo "trivy-scan: ${{ inputs.trivy-scan }}" + echo "grype-scan: ${{ inputs.grype-scan }}" + echo "continue-on-error: ${{ inputs.continue-on-error }}" + echo "only-fixed: ${{ inputs.only-fixed }}" + echo "1. ===================================================================================" + yq -oj '.' $CONFIG_FILE + echo "2. ===================================================================================" + yq -oj '.' $CONFIG_FILE | jq -c 'to_entries | map({repo: .key, image: .value[]}) | {packages: .}' + echo "3. ===================================================================================" + + packages=$(yq -oj '.' $CONFIG_FILE | jq -c 'to_entries | map({repo: .key, image: .value[]})') + echo "packages=$packages" >> $GITHUB_OUTPUT + + security-scan-matrix: + needs: load-config + permissions: + security-events: write + contents: read + packages: read + strategy: + fail-fast: false + matrix: + package: "${{ fromJson(needs.load-config.outputs.packages) }}" + name: "${{ matrix.package.image }}" + uses: netcracker/qubership-workflow-hub/.github/workflows/re-security-scan.yml@v2.0.10 + with: + target: 'docker' + image: ${{ matrix.package.image }} + only-high-critical: ${{ (github.event_name == 'schedule' && true) || inputs.only-high-critical }} + trivy-scan: ${{ (github.event_name == 'schedule' && true) || inputs.trivy-scan }} + grype-scan: ${{ (github.event_name == 'schedule' && true) || inputs.grype-scan }} + continue-on-error: ${{ (github.event_name == 'schedule' && true) || inputs.continue-on-error }} + only-fixed: ${{ (github.event_name == 'schedule' && true) || inputs.only-fixed }} + upload-sarif-to-security: false + + create-report: + needs: [security-scan-matrix] + if: always() + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + path: repo + persist-credentials: true + fetch-depth: 0 + + - name: Ensure branch exists + working-directory: repo + run: | + if git ls-remote --exit-code --heads origin "${{ env.REPORT_BRANCH }}" >/dev/null 2>&1; then + git fetch origin "${{ env.REPORT_BRANCH }}" + git checkout "${{ env.REPORT_BRANCH }}" + else + git checkout -b "${{ env.REPORT_BRANCH }}" + git push -u origin "${{ env.REPORT_BRANCH }}" + fi + + - name: Download artifacts + uses: actions/download-artifact@v7 + with: + pattern: '*.sarif' + path: ./sarif + merge-multiple: true + + - name: Generate report + env: + ACTOR: ${{ github.actor }} + run: | + ### Generating CSV report + mkdir -p repo + cur_date=$(date +%Y-%m-%d) + cur_time=$(date +%H-%M-%S) + cur_date_time=${cur_date}_${cur_time} + report_file_name=report-${cur_date_time}.csv + report_dir=repo/reports/${cur_date} + mkdir -p $report_dir + report_file_path=${report_dir}/${report_file_name} + echo "Report file path: ${report_file_path}" + for component in $(yq e 'keys[]' repo/${CONFIG_FILE}); do + echo "Processing $component's images..." + images=$(yq e ".${component}[]" repo/${CONFIG_FILE}) + for image in $images; do + echo "Image: $image" + SHORT_NAME=${image##*/} + SAFE_NAME=${SHORT_NAME//:/_} + SAFE_NAME=${SAFE_NAME//\//_} + SAFE_NAME=${SAFE_NAME//-/_} + echo "Safe name: $SAFE_NAME" + ls -la ./sarif + echo "[DEBUG]: find ./sarif -name grype-${SAFE_NAME}*.csv -o -name trivy-${SAFE_NAME}*.csv" + + for f in $(find ./sarif -name grype-${SAFE_NAME}*.csv -o -name trivy-${SAFE_NAME}*.csv); do + echo "File: $f" + echo "\"Componenet\",$(head -n 1 "$f")" > "${f}__new" + tail -n +2 "$f" | sed "s/^/\"${component}\",/" >> "${f}__new" + done + done + done + :> ${report_file_path} + i=0 + for f in $(find ./sarif -name *.csv__new | sort); do + if [ $i -eq 0 ]; then + cat $f >> ${report_file_path} + else + tail -n +2 $f >> ${report_file_path} + fi + i=$((i + 1)) + done + + - name: Commit and Push Report + env: + ACTOR: ${{ github.actor }} + run: | + cd repo + git config --global user.name "$ACTOR" + git config --global user.email "$ACTOR@users.noreply.github.com" + git add . + git commit -m "CSV report ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" || echo "No changes" + git push origin "${REPORT_BRANCH}"