virustotal_api 0.5.0 → 0.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 68e1f3494830e62ef04f24a74431a540d3dd6943ee329b772b8a3629798f0856
4
- data.tar.gz: 58e0b36a8a6745b2db5957ab4b48da429f9ec154b1116d0110933cbc54d9f456
3
+ metadata.gz: 4d61c90abdeb3a513e29da52a083c10044eace4aa1f51e6b758798abfee9137a
4
+ data.tar.gz: eae6f4130f49c3e5b6d17553aaf4c4e6725e7e74260ae2c0c250bc0130823c55
5
5
  SHA512:
6
- metadata.gz: 03cf94231610ed5e8002c60dde3cc6d3b3d4ab52682be470023911559c0df6f2cf9230532fe3f002bd2587268405b086742e73a9edba86a4de49eaca37ab1b6b
7
- data.tar.gz: a831140e24d0302e971a33f3b44d7c9760aa271b27d4036bf310ada72f09aa9cd11d1c685793d2a78a0ac6814725de873f8ea6419e92461febef84bb909f2065
6
+ metadata.gz: ef0c2142c1e1ad07be96a88a035f7c906c22c67bb183e7c5906256a1ba83a03378eb985eb02fae68362bb9d9e1439fffef7c82eccfd9a3004144ac6640dd14f3
7
+ data.tar.gz: 2016ad82dadcc09fd03e3ca89cc324bcf7670a3a762a0ea1464569171e589e9d83052f7f95210406747f3d7b3b0ff93e8f67801a35c8d1d42bb482270b036717
@@ -0,0 +1,38 @@
1
+ ---
2
+ name: Bug report
3
+ about: Create a report to help us improve
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Describe the bug**
11
+ A clear and concise description of what the bug is.
12
+
13
+ **To Reproduce**
14
+ Steps to reproduce the behavior:
15
+ 1. Go to '...'
16
+ 2. Click on '....'
17
+ 3. Scroll down to '....'
18
+ 4. See error
19
+
20
+ **Expected behavior**
21
+ A clear and concise description of what you expected to happen.
22
+
23
+ **Screenshots**
24
+ If applicable, add screenshots to help explain your problem.
25
+
26
+ **Desktop (please complete the following information):**
27
+ - OS: [e.g. iOS]
28
+ - Browser [e.g. chrome, safari]
29
+ - Version [e.g. 22]
30
+
31
+ **Smartphone (please complete the following information):**
32
+ - Device: [e.g. iPhone6]
33
+ - OS: [e.g. iOS8.1]
34
+ - Browser [e.g. stock browser, safari]
35
+ - Version [e.g. 22]
36
+
37
+ **Additional context**
38
+ Add any other context about the problem here.
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest an idea for this project
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Is your feature request related to a problem? Please describe.**
11
+ A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12
+
13
+ **Describe the solution you'd like**
14
+ A clear and concise description of what you want to happen.
15
+
16
+ **Describe alternatives you've considered**
17
+ A clear and concise description of any alternative solutions or features you've considered.
18
+
19
+ **Additional context**
20
+ Add any other context or screenshots about the feature request here.
@@ -0,0 +1,11 @@
1
+ CHANGELOG: no-impact/Added/Changed/Deprecated/Removed/Fixed/Security
2
+
3
+ ## Summary
4
+
5
+ ## Testing
6
+
7
+ 1. _Describe how to test this change_
8
+
9
+ ## Other Information
10
+
11
+ _Include screenshots, GIFs, and/or API responses as appropriate._
@@ -7,17 +7,56 @@ on:
7
7
  branches: [ master ]
8
8
 
9
9
  jobs:
10
- Test:
10
+ Test-Ruby-2-5:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v2
14
+ - name: Set up Ruby
15
+ # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
16
+ # change this to (see https://github.com/ruby/setup-ruby#versioning):
17
+ uses: ruby/setup-ruby@v1.70.1
18
+ with:
19
+ ruby-version: 2.5
20
+ - name: Show Ruby Version
21
+ run: ruby --version
22
+ - name: Install dependencies
23
+ run: bundle install
24
+ - name: Lint
25
+ run: bundle exec rake rubocop
26
+ - name: Run tests
27
+ run: bundle exec rake
28
+
29
+ Test-Ruby-2-7:
30
+ runs-on: ubuntu-latest
31
+ steps:
32
+ - uses: actions/checkout@v2
33
+ - name: Set up Ruby
34
+ # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
35
+ # change this to (see https://github.com/ruby/setup-ruby#versioning):
36
+ uses: ruby/setup-ruby@v1.70.1
37
+ with:
38
+ ruby-version: 2.7
39
+ - name: Show Ruby Version
40
+ run: ruby --version
41
+ - name: Install dependencies
42
+ run: bundle install
43
+ - name: Lint
44
+ run: bundle exec rake rubocop
45
+ - name: Run tests
46
+ run: bundle exec rake
47
+
48
+ Test-Ruby-3-0:
11
49
  runs-on: ubuntu-latest
12
-
13
50
  steps:
14
51
  - uses: actions/checkout@v2
15
52
  - name: Set up Ruby
16
53
  # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
17
54
  # change this to (see https://github.com/ruby/setup-ruby#versioning):
18
- uses: ruby/setup-ruby@v1.46.0
55
+ uses: ruby/setup-ruby@v1.70.1
19
56
  with:
20
- ruby-version: 2.6
57
+ ruby-version: 3.0
58
+ - name: Show Ruby Version
59
+ run: ruby --version
21
60
  - name: Install dependencies
22
61
  run: bundle install
23
62
  - name: Lint
data/CHANGELOG.md CHANGED
@@ -1,8 +1,32 @@
1
1
  # VirusTotal API Changelog
2
2
 
3
+ ## [0.5.5] - 2021-05-10
4
+ * Add support for larger files
5
+ * [@Grandman](https://github.com/Grandman)
6
+
7
+ ## [0.5.4] - 2020-12-10
8
+ * Manage bad requests like not found
9
+ * Use strict base64 encoding
10
+ * [@crondaemon](https://github.com/crondaemon)
11
+
12
+ ## [0.5.3] = 2020-10-12
13
+
14
+ ## [0.5.2] - 2020-10-06
15
+
16
+ * Fix Fix exists? check
17
+ * Fix detected_by for File
18
+ * Fix RateLimitError
19
+ * Added User and Group API
20
+ * [@jonnynux](https://github.com/jonnynux)
21
+
22
+ ## [0.5.1] - 2020-10-06
23
+
24
+ * Downgrade ruby requirement to 2.5.
25
+ * [@crondaemon](https://github.com/crondaemon)
26
+
3
27
  ## [0.5.0] - 2020-09-02
4
28
 
5
- * Full rework to support API V3.
29
+ * Full rework to support API V3 [#30](https://github.com/pwelch/virustotal_api/pull/30)
6
30
  * [@crondaemon](https://github.com/crondaemon) & [@jonnynux](https://github.com/jonnynux)
7
31
  * Move to Ruby 2.6 for minimum Ruby version
8
32
 
data/README.md CHANGED
@@ -65,7 +65,10 @@ require 'virustotal_api'
65
65
  file = '/path/to/file'
66
66
  api_key = 'MY_API_KEY'
67
67
 
68
+ # for upload file
68
69
  vtscan = VirustotalAPI::File.upload(file, api_key)
70
+ # or large file (more than 32MB)
71
+ vtscan = VirustotalAPI::File.upload_large(file, api_key)
69
72
 
70
73
  # Virustotal ID of file
71
74
  vtscan.id
@@ -117,7 +120,7 @@ vturl_report.exists?
117
120
 
118
121
  # URL for Report (if it exists)
119
122
  vturl_report.report_url
120
- # => "https://www.virustotal.com/api/v3/urls/dd014af5ed6b38d9130e3f466f850e46d21b951199d53a18ef29ee9341614eaf/"
123
+ # => "https://www.virustotal.com/api/v3/urls/dd014af5ed6b38d9130e3f466f850e46d21b951199d53a18ef29ee9341614eaf"
121
124
 
122
125
  # Report results (if they exist) are available via #report
123
126
  vturl_report.report['data']['attributes']['last_analysis_results']['Avira']
@@ -161,6 +164,10 @@ vtip_report = VirustotalAPI::IP.find(ip, api_key)
161
164
  vtip_report.exists?
162
165
  # => true
163
166
 
167
+ # URL for Report (if it exists)
168
+ vtip_report.report_url
169
+ # => "https://www.virustotal.com/api/v3/ip_addresses/8.8.8.8"
170
+
164
171
  # Report results (if they exist) are available via #report
165
172
  vtip_report.report
166
173
  # => Hash of report results
@@ -180,17 +187,60 @@ vtdomain_report = VirustotalAPI::Domain.find(domain, api_key)
180
187
  vtdomain_report.exists?
181
188
  # => true
182
189
 
190
+ # URL for Report (if it exists)
191
+ vtdomain_report.report_url
192
+ # => "https://www.virustotal.com/api/v3/domains/virustotal.com"
193
+
183
194
  # Report results (if they exist) are available via #report
184
195
  vtdomain_report.report
185
196
  # => Hash of report results
186
197
  ```
187
198
 
199
+ ### User Find
200
+
201
+ ```ruby
202
+ require 'virustotal_api'
203
+
204
+ user_key = 'user_key' # user_id or api_key
205
+ api_key = 'MY_API_KEY'
206
+
207
+ vtuser_report = VirustotalAPI::User.find(user_key, api_key)
208
+
209
+ # Does the resource have any results?
210
+ vtuser_report.exists?
211
+ # => true
212
+
213
+ # Report results (if they exist) are available via #report
214
+ vtuser_report.report
215
+ # => Hash of report results
216
+ ```
217
+
218
+ ### Group Find
219
+
220
+ ```ruby
221
+ require 'virustotal_api'
222
+
223
+ group_id = 'GROUP_id'
224
+ api_key = 'MY_API_KEY'
225
+
226
+ vtgroup_report = VirustotalAPI::Group.find(group_id, api_key)
227
+
228
+ # Does the resource have any results?
229
+ vtgroup_report.exists?
230
+ # => true
231
+
232
+ # Report results (if they exist) are available via #report
233
+ vtgroup_report.report
234
+ # => Hash of report results
235
+ ```
236
+
188
237
  ## Contributors
189
238
 
190
- - [@postmodern](https://github.com/postmodern)
191
- - [@mkunkel](https://github.com/mkunkel)
192
239
  - [@jonnynux](https://github.com/jonnynux)
193
240
  - [@crondaemon](https://github.com/crondaemon/)
241
+ - [@postmodern](https://github.com/postmodern)
242
+ - [@mkunkel](https://github.com/mkunkel)
243
+ - [@Grandman](https://github.com/Grandman)
194
244
 
195
245
  ## Contributing
196
246
 
@@ -3,7 +3,9 @@
3
3
  require 'virustotal_api/analysis'
4
4
  require 'virustotal_api/domain'
5
5
  require 'virustotal_api/file'
6
+ require 'virustotal_api/group'
6
7
  require 'virustotal_api/ip'
7
8
  require 'virustotal_api/url'
8
9
  require 'virustotal_api/uri'
10
+ require 'virustotal_api/user'
9
11
  require 'virustotal_api/version'
@@ -5,13 +5,6 @@ require_relative 'base'
5
5
  module VirustotalAPI
6
6
  # A class for '/analyses' API
7
7
  class Analysis < Base
8
- attr_reader :report
9
-
10
- # rubocop:disable Lint/MissingSuper
11
- def initialize(report)
12
- @report = report
13
- end
14
-
15
8
  # @param [String] id The Virustotal ID to get the report for.
16
9
  # @param [String] api_key The key for virustotal
17
10
  # @return [VirustotalAPI::IP] Report
@@ -21,4 +14,3 @@ module VirustotalAPI
21
14
  end
22
15
  end
23
16
  end
24
- # rubocop:enable Lint/MissingSuper
@@ -9,10 +9,12 @@ require 'base64'
9
9
  module VirustotalAPI
10
10
  # The base class implementing the raw calls to Virustotal API V3.
11
11
  class Base
12
- attr_reader :report
12
+ attr_reader :report, :report_url, :id
13
13
 
14
14
  def initialize(report)
15
- @report = report
15
+ @report = report
16
+ @report_url = report&.dig('data', 'links', 'self')
17
+ @id = report&.dig('data', 'id')
16
18
  end
17
19
 
18
20
  # @return [String] string of API URI class method
@@ -20,6 +22,14 @@ module VirustotalAPI
20
22
  VirustotalAPI::URI
21
23
  end
22
24
 
25
+ def self.perform(path, api_key, method = :get, options = {})
26
+ base_perform(api_uri + path, api_key, method, options)
27
+ end
28
+
29
+ def self.perform_absolute(url, api_key, method = :get, options = {})
30
+ base_perform(url, api_key, method, options)
31
+ end
32
+
23
33
  # The actual method performing a call to Virustotal
24
34
  #
25
35
  # @param [String] url The url of the API
@@ -27,22 +37,28 @@ module VirustotalAPI
27
37
  # @param [String] method The HTTP method to use
28
38
  # @param [Hash] options Options to pass as payload
29
39
  # @return [VirustotalAPI::Domain] Report Search Result
30
- def self.perform(url, api_key, method = :get, options = {})
40
+ def self.base_perform(url, api_key, method = :get, options = {})
31
41
  response = RestClient::Request.execute(
32
42
  method: method,
33
- url: api_uri + url,
43
+ url: url,
34
44
  headers: { 'x-apikey': api_key },
35
45
  payload: options
36
46
  )
37
47
  JSON.parse(response.body)
38
- rescue RestClient::NotFound
39
- nil
48
+ rescue RestClient::NotFound, RestClient::BadRequest
49
+ {}
40
50
  rescue RestClient::Unauthorized
41
51
  # Raise a custom exception not to expose the underlying
42
52
  # HTTP client.
43
53
  raise VirustotalAPI::Unauthorized
54
+ rescue RestClient::TooManyRequests
55
+ # Raise a custom exception not to expose the underlying
56
+ # HTTP client.
57
+ raise VirustotalAPI::RateLimitError
44
58
  end
45
59
 
60
+ private_class_method :base_perform
61
+
46
62
  # @return [String] string of API URI instance method
47
63
  def api_uri
48
64
  self.class.api_uri
@@ -56,7 +72,7 @@ module VirustotalAPI
56
72
  # Generate a URL identifier.
57
73
  # @see https://developers.virustotal.com/v3.0/reference#url
58
74
  def self.url_identifier(url)
59
- Base64.encode64(url).strip.gsub('=', '')
75
+ Base64.strict_encode64(url).strip.gsub('=', '')
60
76
  end
61
77
  end
62
78
  end
@@ -5,11 +5,6 @@ require_relative 'base'
5
5
  module VirustotalAPI
6
6
  # A class for '/domains' API
7
7
  class Domain < Base
8
- # rubocop:disable Lint/UselessMethodDefinition
9
- def initialize(report)
10
- super(report)
11
- end
12
-
13
8
  # Find a domain.
14
9
  #
15
10
  # @param [String] domain The domain to search
@@ -21,4 +16,3 @@ module VirustotalAPI
21
16
  end
22
17
  end
23
18
  end
24
- # rubocop:enable Lint/UselessMethodDefinition
@@ -5,14 +5,6 @@ require_relative 'base'
5
5
  module VirustotalAPI
6
6
  # A class for '/files' API
7
7
  class File < Base
8
- attr_reader :id, :report_url
9
-
10
- def initialize(report)
11
- super(report)
12
- @id = report&.dig('data', 'id')
13
- @report_url = report&.dig('data', 'links', 'self')
14
- end
15
-
16
8
  # Find a hash.
17
9
  #
18
10
  # @param [String] resource file as a md5/sha1/sha256 hash
@@ -31,7 +23,20 @@ module VirustotalAPI
31
23
  # @return [VirusotalAPI::File] Report
32
24
  def self.upload(file_path, api_key, opts = {})
33
25
  filename = opts.fetch('filename') { ::File.basename(file_path) }
34
- report = perform('/files', api_key, :post, filename: filename, file: ::File.open(file_path, 'r'))
26
+ report = perform('/files', api_key, :post, filename: filename, file: ::File.open(file_path, 'r'))
27
+ new(report)
28
+ end
29
+
30
+ # Upload a new file with size more than 32MB.
31
+ #
32
+ # @param [String] file_path for file to be sent for scan
33
+ # @param [String] api_key The key for virustotal
34
+ # @param [Hash] opts hash for additional options
35
+ # @return [VirusotalAPI::File] Report
36
+ def self.upload_large(file_path, api_key, opts = {})
37
+ filename = opts.fetch('filename') { ::File.basename(file_path) }
38
+ url = upload_url(api_key)
39
+ report = perform_absolute(url, api_key, :post, filename: filename, file: ::File.open(file_path, 'r'))
35
40
  new(report)
36
41
  end
37
42
 
@@ -45,12 +50,18 @@ module VirustotalAPI
45
50
  new(report)
46
51
  end
47
52
 
53
+ # @return [String] url for upload file
54
+ def self.upload_url(api_key)
55
+ data = perform('/files/upload_url', api_key)
56
+ data&.dig('data')
57
+ end
58
+
48
59
  # Check if the submitted hash is detected by an AV engine.
49
60
  #
50
61
  # @param [String] engine The engine to check.
51
62
  # @return [Boolean] true if detected
52
63
  def detected_by(engine)
53
- report['data']['attributes']['last_analysis_results'][engine]['category'] == 'harmless'
64
+ report&.dig('data', 'attributes', 'last_analysis_results', engine, 'category') == 'malicious'
54
65
  end
55
66
  end
56
67
  end