Skip to content

Commit 43e4215

Browse files
authored
RI-5395: Run VirusTotal Analyze as crone job + support batch validation (#4310)
* use upload files instead of url (different VT API) * run array of files * add midnight run
1 parent a0ae1c3 commit 43e4215

File tree

1 file changed

+94
-41
lines changed

1 file changed

+94
-41
lines changed

.github/workflows/nightly-virustotal-analyze.yml

Lines changed: 94 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,84 +3,137 @@ name: Nightly Virustotal Analyze
33
on:
44
workflow_dispatch:
55
inputs:
6+
mode:
7+
description: "Choose 'single' or 'all'"
8+
required: true
9+
default: 'all'
10+
type: string
611
file_url:
7-
description: Provide a file URL for manual scanning (optional)
12+
description: "Provide a file URL for single file scanning (required for 'single' mode)"
813
required: false
914
default: 'https://s3.amazonaws.com/redisinsight.download/public/latest/Redis-Insight-mac-arm64.dmg'
1015
type: string
16+
schedule:
17+
- cron: '0 0 * * *'
1118

1219
env:
1320
VIRUSTOTAL_API_KEY: ${{ secrets.VIRUSTOTAL_API_KEY }}
21+
DEFAULT_FILES: |
22+
https://s3.amazonaws.com/redisinsight.download/public/latest/Redis-Insight-mac-x64.dmg
23+
https://s3.amazonaws.com/redisinsight.download/public/latest/Redis-Insight-mac-arm64.dmg
24+
https://s3.amazonaws.com/redisinsight.download/public/latest/Redis-Insight-win-installer.exe
25+
https://s3.amazonaws.com/redisinsight.download/public/latest/Redis-Insight-linux-x86_64.AppImage
26+
https://s3.amazonaws.com/redisinsight.download/public/latest/Redis-Insight-linux-amd64.deb
1427
1528
jobs:
1629
analyze:
17-
name: Analyze file
30+
name: VirusTotal Analyze
31+
runs-on: ubuntu-latest
32+
outputs:
33+
files: ${{ steps.setup_matrix.outputs.files }}
34+
steps:
35+
- name: Determine mode and files
36+
id: setup_matrix
37+
run: |
38+
mode="${{ github.event.inputs.mode }}"
39+
file_url="${{ github.event.inputs.file_url }}"
40+
41+
if [ "$mode" == "single" ] && [ -z "$file_url" ]; then
42+
echo "Error: For 'single' mode, a file URL must be provided."
43+
exit 1
44+
fi
45+
46+
if [ "$mode" == "single" ]; then
47+
echo "files=[\"$file_url\"]" >> $GITHUB_OUTPUT
48+
else
49+
files_json=$(echo "${{ env.DEFAULT_FILES }}" | sed '/^$/d' | jq -R -s -c 'split("\n")[:-1]')
50+
echo "files=$files_json" >> $GITHUB_OUTPUT
51+
fi
52+
53+
analyze_files:
54+
name: Analyze each file
55+
needs: analyze
1856
runs-on: ubuntu-latest
1957

58+
strategy:
59+
matrix:
60+
file: ${{ fromJson(needs.analyze.outputs.files) }}
61+
2062
steps:
21-
- name: Use File URL
22-
id: file_url_check
63+
- name: Download file
2364
run: |
24-
echo "Using File URL: ${{ github.event.inputs.file_url }}"
25-
echo "FILE_URL=${{ github.event.inputs.file_url }}" >> $GITHUB_ENV
65+
echo "Downloading: ${{ matrix.file }}"
66+
curl -sLo file_to_analyze "${{ matrix.file }}"
2667
27-
- name: Send URL to scan
68+
- name: Get upload URL
69+
id: get_upload_url
2870
run: |
29-
url="${{ env.FILE_URL }}"
30-
echo "URL to check: $url"
71+
upload_url=$(curl -sq -XGET https://www.virustotal.com/api/v3/files/upload_url \
72+
-H "x-apikey: $VIRUSTOTAL_API_KEY" | jq -r '.data')
73+
74+
if [ -z "$upload_url" ] || [ "$upload_url" == "null" ]; then
75+
echo "Failed to retrieve upload URL for ${{ matrix.file }}"
76+
exit 1
77+
fi
78+
79+
echo "UPLOAD_URL=$upload_url" >> $GITHUB_ENV
3180
32-
# Upload the URL to VirusTotal
33-
analysedId=$(curl -sq -XPOST https://www.virustotal.com/api/v3/urls \
81+
- name: Upload file to VirusTotal
82+
id: upload_file
83+
run: |
84+
upload_url="${{ env.UPLOAD_URL }}"
85+
analyzed_id=$(curl -sq -XPOST "$upload_url" \
3486
-H "x-apikey: $VIRUSTOTAL_API_KEY" \
35-
--form url=${url} | jq -r '.data.id')
87+
--form "file=@file_to_analyze" | jq -r '.data.id')
3688
37-
if [ "$analysedId" == "null" ]; then
38-
echo 'Status is null, something went wrong';
39-
exit 1;
89+
if [ -z "$analyzed_id" ] || [ "$analyzed_id" == "null" ]; then
90+
echo "Failed to upload file: ${{ matrix.file }}"
91+
exit 1
4092
fi
4193
42-
echo "ANALYZED_ID=$analysedId" >> $GITHUB_ENV
94+
echo "ANALYZED_ID=$analyzed_id" >> $GITHUB_ENV
4395
4496
- name: Check analyze status
4597
run: |
46-
echo "Virustotal Analyzed ID: ${ANALYZED_ID}"
47-
retryAttempts="50"
48-
intervalTime=30
98+
analyzed_id="${{ env.ANALYZED_ID }}"
99+
retry_attempts=50
100+
interval_time=30
49101
50-
until [ "$retryAttempts" == "0" ]; do
51-
analyzeStatus=$(curl -sq -XGET https://www.virustotal.com/api/v3/analyses/${ANALYZED_ID} \
102+
until [ "$retry_attempts" == "0" ]; do
103+
analyze_status=$(curl -sq -XGET https://www.virustotal.com/api/v3/analyses/${analyzed_id} \
52104
-H "x-apikey: $VIRUSTOTAL_API_KEY" | jq -r '.data.attributes.status')
53105
54-
if [ "$analyzeStatus" == "completed" ]; then
55-
echo "Current status: ${analyzeStatus}"
106+
if [ "$analyze_status" == "completed" ]; then
56107
break
57-
else
58-
echo "Current status: ${analyzeStatus}, retries left: ${retryAttempts}"
59-
sleep $intervalTime
60-
retryAttempts=$((retryAttempts - 1))
61108
fi
109+
110+
echo "Current status: $analyze_status, retries left: $retry_attempts"
111+
sleep $interval_time
112+
retry_attempts=$((retry_attempts - 1))
62113
done
63114
64-
if [ "$analyzeStatus" != "completed" ]; then
65-
echo 'Analyze is not completed'
115+
if [ "$analyze_status" != "completed" ]; then
116+
echo "Analysis not completed for ${{ matrix.file }}"
66117
exit 1
67118
fi
68119
69120
- name: Validate analyze
70-
id: validate
71121
run: |
72-
analyzeStats=$(curl -sq -XGET https://www.virustotal.com/api/v3/analyses/${ANALYZED_ID} \
73-
-H "x-apikey: $VIRUSTOTAL_API_KEY" | jq -r '.data.attributes.stats')
122+
analyzed_id="${{ env.ANALYZED_ID }}"
123+
analysis=$(curl -sq -XGET "https://www.virustotal.com/api/v3/analyses/${analyzed_id}" \
124+
-H "x-apikey: $VIRUSTOTAL_API_KEY")
74125
75-
analazedMalicious=$(echo ${analyzeStats} | jq '.malicious')
76-
analazedSuspicious=$(echo ${analyzeStats} | jq '.suspicious')
77-
analazedHarmless=$(echo ${analyzeStats} | jq '.harmless')
126+
analyze_stats=$(echo "$analysis" | jq -r '.data.attributes.stats')
78127
79-
echo "Results: Malicious: ${analazedMalicious}, Suspicious: ${analazedSuspicious}, Harmless: ${analazedHarmless}"
128+
malicious=$(echo "$analyze_stats" | jq '.malicious')
129+
suspicious=$(echo "$analyze_stats" | jq '.suspicious')
130+
suspicious=$(echo "$analyze_stats" | jq '.suspicious')
131+
harmless=$(echo "$analyze_stats" | jq '.harmless')
80132
81-
if [ "$analazedMalicious" != "0" ] || [ "$analazedSuspicious" != "0" ]; then
82-
echo "FAILED=true" >> $GITHUB_ENV
83-
echo 'Found dangers'
84-
else
85-
echo "FAILED=false" >> $GITHUB_ENV
133+
echo "Results for ${{ matrix.file }}: Malicious: $malicious, Suspicious: $suspicious, Harmless: $harmless"
134+
135+
if [ "$malicious" != "0" ] || [ "$suspicious" != "0" ]; then
136+
echo "File ${{ matrix.file }} is flagged as potentially harmful."
137+
echo "$analysis" | jq -r '.data.attributes.results[] | select(.result == "malicious" or .result == "suspicious")'
138+
exit 1
86139
fi

0 commit comments

Comments
 (0)