virustotal_api 0.4.1 → 0.5.0

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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +26 -0
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +12 -5
  5. data/CHANGELOG.md +7 -2
  6. data/README.md +48 -56
  7. data/lib/virustotal_api.rb +5 -7
  8. data/lib/virustotal_api/analysis.rb +24 -0
  9. data/lib/virustotal_api/base.rb +35 -10
  10. data/lib/virustotal_api/domain.rb +24 -0
  11. data/lib/virustotal_api/exceptions.rb +3 -0
  12. data/lib/virustotal_api/file.rb +56 -0
  13. data/lib/virustotal_api/ip.rb +24 -0
  14. data/lib/virustotal_api/uri.rb +2 -1
  15. data/lib/virustotal_api/url.rb +46 -0
  16. data/lib/virustotal_api/version.rb +2 -1
  17. data/test/analysis_test.rb +23 -0
  18. data/test/base_test.rb +8 -28
  19. data/test/domain_test.rb +32 -0
  20. data/test/exceptions_test.rb +14 -0
  21. data/test/file_test.rb +68 -0
  22. data/test/fixtures/analysis.yml +544 -0
  23. data/test/fixtures/domain.yml +830 -0
  24. data/test/fixtures/file_analyse.yml +52 -0
  25. data/test/fixtures/file_find.yml +1236 -0
  26. data/test/fixtures/file_unauthorized.yml +51 -0
  27. data/test/fixtures/file_upload.yml +54 -0
  28. data/test/fixtures/ip.yml +716 -0
  29. data/test/fixtures/unscanned_url_find.yml +44 -0
  30. data/test/fixtures/url_analyse.yml +52 -0
  31. data/test/fixtures/url_find.yml +599 -0
  32. data/test/{ip_report_test.rb → ip_test.rb} +4 -4
  33. data/test/uri_test.rb +1 -1
  34. data/test/url_test.rb +65 -0
  35. data/test/version_test.rb +1 -1
  36. data/virustotal_api.gemspec +10 -8
  37. metadata +86 -70
  38. data/.github/workflows/gem_publish.yml +0 -38
  39. data/lib/virustotal_api/domain_report.rb +0 -36
  40. data/lib/virustotal_api/file_report.rb +0 -37
  41. data/lib/virustotal_api/file_rescan.rb +0 -36
  42. data/lib/virustotal_api/file_scan.rb +0 -38
  43. data/lib/virustotal_api/ip_report.rb +0 -36
  44. data/lib/virustotal_api/url_report.rb +0 -41
  45. data/lib/virustotal_api/url_scan.rb +0 -36
  46. data/test/domain_report_test.rb +0 -32
  47. data/test/file_report_test.rb +0 -36
  48. data/test/file_rescan_test.rb +0 -32
  49. data/test/file_scan_test.rb +0 -30
  50. data/test/fixtures/domain_report.yml +0 -311
  51. data/test/fixtures/ip_report.yml +0 -1323
  52. data/test/fixtures/queue_unscanned_url_report.yml +0 -46
  53. data/test/fixtures/report.yml +0 -110
  54. data/test/fixtures/report_not_found.yml +0 -42
  55. data/test/fixtures/request_forbidden.yml +0 -38
  56. data/test/fixtures/rescan.yml +0 -47
  57. data/test/fixtures/scan.yml +0 -49
  58. data/test/fixtures/unscanned_url_report.yml +0 -43
  59. data/test/fixtures/url_report.yml +0 -95
  60. data/test/fixtures/url_scan.yml +0 -48
  61. data/test/url_report_test.rb +0 -57
  62. data/test/url_scan_test.rb +0 -30
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 59f51d8dce27daace930afc9786485d497e79b3ba9afc6b82bffbb1ac1c98b36
4
- data.tar.gz: 1fe1adf06f5135342dd48cade1d28c78a97530885e51e6d0993d0a971e31cec4
3
+ metadata.gz: 68e1f3494830e62ef04f24a74431a540d3dd6943ee329b772b8a3629798f0856
4
+ data.tar.gz: 58e0b36a8a6745b2db5957ab4b48da429f9ec154b1116d0110933cbc54d9f456
5
5
  SHA512:
6
- metadata.gz: 30985ac7e3aec76bf9fd6ab41f9b1b1ec46edb96ba5e3ab12e9d1c993aeff665cc41fb5644db97afb26d41605208f4b0a116856fed5cfe22872571da429e3882
7
- data.tar.gz: ea9be7f207a5805fecc1e1e321c07ade17cafc1eb0b1c85416117985f54837b6951c6285562f0ffffac32933fd9ff0bd66e1561f0d15ccb6555f0998d6d8a0de
6
+ metadata.gz: 03cf94231610ed5e8002c60dde3cc6d3b3d4ab52682be470023911559c0df6f2cf9230532fe3f002bd2587268405b086742e73a9edba86a4de49eaca37ab1b6b
7
+ data.tar.gz: a831140e24d0302e971a33f3b44d7c9760aa271b27d4036bf310ada72f09aa9cd11d1c685793d2a78a0ac6814725de873f8ea6419e92461febef84bb909f2065
@@ -0,0 +1,26 @@
1
+ name: Ruby
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ pull_request:
7
+ branches: [ master ]
8
+
9
+ jobs:
10
+ Test:
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - uses: actions/checkout@v2
15
+ - name: Set up Ruby
16
+ # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
17
+ # change this to (see https://github.com/ruby/setup-ruby#versioning):
18
+ uses: ruby/setup-ruby@v1.46.0
19
+ with:
20
+ ruby-version: 2.6
21
+ - name: Install dependencies
22
+ run: bundle install
23
+ - name: Lint
24
+ run: bundle exec rake rubocop
25
+ - name: Run tests
26
+ run: bundle exec rake
data/.gitignore CHANGED
@@ -12,3 +12,4 @@
12
12
  *.o
13
13
  *.a
14
14
  mkmf.log
15
+ .rake_tasks~
@@ -1,13 +1,14 @@
1
1
  # This is the configuration used to check the rubocop source code.
2
2
 
3
3
  AllCops:
4
+ NewCops: enable
4
5
  Exclude:
5
6
  - 'test/fixtures/*'
6
7
 
7
8
  Style/StringLiterals:
8
9
  Enabled: true
9
10
 
10
- Style/UnneededPercentQ:
11
+ Style/RedundantPercentQ:
11
12
  Enabled: true
12
13
 
13
14
  # Disabled Checks
@@ -20,13 +21,19 @@ Style/PercentLiteralDelimiters:
20
21
  Style/RegexpLiteral:
21
22
  Enabled: false
22
23
 
23
- Style/BracesAroundHashParameters:
24
- Enabled: false
25
-
26
24
  Lint/MissingCopEnableDirective:
27
25
  Exclude:
28
26
  - 'test/base_test.rb'
29
27
 
30
- Naming/UncommunicativeMethodParamName:
28
+ Naming/MethodParameterName:
31
29
  Exclude:
32
30
  - 'lib/virustotal_api/ip_report.rb'
31
+
32
+ Layout/LineLength:
33
+ Enabled: false
34
+
35
+ Metrics/MethodLength:
36
+ Enabled: false
37
+
38
+ Gemspec/RequiredRubyVersion:
39
+ Enabled: false
@@ -1,10 +1,15 @@
1
1
  # VirusTotal API Changelog
2
2
 
3
+ ## [0.5.0] - 2020-09-02
4
+
5
+ * Full rework to support API V3.
6
+ * [@crondaemon](https://github.com/crondaemon) & [@jonnynux](https://github.com/jonnynux)
7
+ * Move to Ruby 2.6 for minimum Ruby version
8
+
3
9
  ## [0.4.1] - 2019-09-04
4
10
 
5
11
  * Fixed Reponse Parsing
6
- * [@jonnynux](https://github.com/jonnynux)
7
-
12
+ * [@jonnynux](https://github.com/jonnynux)
8
13
 
9
14
  ## [0.4.0] - 2019-07-23
10
15
 
data/README.md CHANGED
@@ -1,9 +1,11 @@
1
1
  # VirustotalAPI
2
2
 
3
- Ruby Gem for [VirusTotal](https://www.virustotal.com) [V2 API](https://www.virustotal.com/en/documentation/public-api/)
3
+ Ruby Gem for [VirusTotal](https://www.virustotal.com) [V3 API](https://developers.virustotal.com/v3.0/reference).
4
+ If you want the version 2, check out the gem versions up to [0.4.0](https://github.com/crondaemon/virustotal_api/tree/v0.4.0).
5
+
6
+ ![Ruby](https://github.com/pwelch/virustotal_api/workflows/Ruby/badge.svg)
4
7
 
5
8
  [![Gem Version](https://badge.fury.io/rb/virustotal_api.svg)](http://badge.fury.io/rb/virustotal_api)
6
- [![CircleCI](https://circleci.com/gh/pwelch/virustotal_api.svg?style=svg)](https://circleci.com/gh/pwelch/virustotal_api)
7
9
 
8
10
  ## Installation
9
11
 
@@ -27,7 +29,7 @@ VirusTotal only allows 4 queries per minute for their Public API. https://www.vi
27
29
 
28
30
  You will need a Private API Key if you require more queries per minute.
29
31
 
30
- ### File Report
32
+ ### File Find
31
33
 
32
34
  ```ruby
33
35
  require 'virustotal_api'
@@ -35,7 +37,7 @@ require 'virustotal_api'
35
37
  sha256 = '01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b'
36
38
  api_key = 'MY_API_KEY'
37
39
 
38
- vtreport = VirustotalAPI::FileReport.find(sha256, api_key)
40
+ vtreport = VirustotalAPI::File.find(sha256, api_key)
39
41
 
40
42
  # Does the resource have any results?
41
43
  vtreport.exists?
@@ -43,14 +45,19 @@ vtreport.exists?
43
45
 
44
46
  # URL for File Report (if it exists)
45
47
  vtreport.report_url
46
- # => "https://www.virustotal.com/file/01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b/analysis/1418032127/"
48
+ # => "https://www.virustotal.com/api/v3/files/01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b"
47
49
 
48
50
  # Report results (if they exist) are available via #report
49
- vtreport.report["scans"]["ClamAV"]
50
- # => {"detected"=>false, "version"=>"0.98.5.0", "result"=>nil, "update"=>"20141208"}
51
+ vtreport.report['data']['attributes']['last_analysis_results']['ClamAV']
52
+ # => {"category"=>"undetected", "engine_name"=>"ClamAV", "engine_update"=>"20200826",
53
+ # "engine_version"=>"0.102.4.0", "method"=>"blacklist", "result"=>nil}
54
+
55
+ # Check whether an Antivirus detected this sample or not
56
+ vtreport.detected_by('ClamAV')
57
+ # => false
51
58
  ```
52
59
 
53
- ### File Scan
60
+ ### File Upload
54
61
 
55
62
  ```ruby
56
63
  require 'virustotal_api'
@@ -58,28 +65,21 @@ require 'virustotal_api'
58
65
  file = '/path/to/file'
59
66
  api_key = 'MY_API_KEY'
60
67
 
61
- vtscan = VirustotalAPI::FileScan.scan(file, api_key)
68
+ vtscan = VirustotalAPI::File.upload(file, api_key)
62
69
 
63
- # Scan ID of file
64
- vtscan.scan_id
70
+ # Virustotal ID of file
71
+ vtscan.id
65
72
  # => "01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b-1419454668"
66
73
 
67
74
  # Response results are available via #response
68
75
  vtscan.report
69
76
  # =>
70
- {
71
- "scan_id"=>"01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b-1419454668",
72
- "sha1"=>"adc83b19e793491b1c6ea0fd8b46cd9f32e592fc",
73
- "resource"=>"01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b",
74
- "response_code"=>1,
75
- "sha256"=>"01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b",
76
- "permalink"=>"https://www.virustotal.com/file/01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b/analysis/1419454668/",
77
- "md5"=>"68b329da9893e34099c7d8ad5cb9c940",
78
- "verbose_msg"=>"Scan request successfully queued, come back later for the report"
79
- }
77
+ {"data"=>
78
+ {"id"=>"MTkxNDBmMjU4ZGY1OGZiYzZjNmU2ODcyMWNhYjhkZTM6MTU5ODUzMTE5OQ==",
79
+ "type"=>"analysis"}}
80
80
  ```
81
81
 
82
- ### File Rescan
82
+ ### File Analyse
83
83
 
84
84
  ```ruby
85
85
  require 'virustotal_api'
@@ -87,25 +87,21 @@ require 'virustotal_api'
87
87
  sha256 = '01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b'
88
88
  api_key = 'MY_API_KEY'
89
89
 
90
- vtrescan = VirustotalAPI::FileRescan.rescan(sha256, api_key)
90
+ vtrescan = VirustotalAPI::File.analyse(sha256, api_key)
91
91
 
92
- # Rescan ID of file
93
- vtrescan.rescan_id
94
- # => "01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b-1562684247"
92
+ # Virustotal ID of file
93
+ vtrescan.id
94
+ # => "MTkxNDBmMjU4ZGY1OGZiYzZjNmU2ODcyMWNhYjhkZTM6MTU5ODUzMTE5OQ=="
95
95
 
96
96
  # Response results are available via #response
97
97
  vtrescan.report
98
98
  # =>
99
- {
100
- "permalink": "https://www.virustotal.com/file/01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b/analysis/1562684247/",
101
- "response_code": 1,
102
- "sha256": "01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b",
103
- "resource": "01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b",
104
- "scan_id": "01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b-1562684247"
105
- }
99
+ {"data"=>
100
+ {"id"=>"MTkxNDBmMjU4ZGY1OGZiYzZjNmU2ODcyMWNhYjhkZTM6MTU5ODUzMTE5OQ==",
101
+ "type"=>"analysis"}}
106
102
  ```
107
103
 
108
- ### URL Report
104
+ ### URL find
109
105
 
110
106
  ```ruby
111
107
  require 'virustotal_api'
@@ -113,7 +109,7 @@ require 'virustotal_api'
113
109
  url = 'http://www.google.com'
114
110
  api_key = 'MY_API_KEY'
115
111
 
116
- vturl_report = VirustotalAPI::URLReport.find(url, api_key)
112
+ vturl_report = VirustotalAPI::URL.find(url, api_key)
117
113
 
118
114
  # Does the resource have any results?
119
115
  vturl_report.exists?
@@ -121,14 +117,14 @@ vturl_report.exists?
121
117
 
122
118
  # URL for Report (if it exists)
123
119
  vturl_report.report_url
124
- # => "https://www.virustotal.com/url/dd014af5ed6b38d9130e3f466f850e46d21b951199d53a18ef29ee9341614eaf/analysis/1419457210/"
120
+ # => "https://www.virustotal.com/api/v3/urls/dd014af5ed6b38d9130e3f466f850e46d21b951199d53a18ef29ee9341614eaf/"
125
121
 
126
122
  # Report results (if they exist) are available via #report
127
- vturl_report.report["scans"]["Opera"]
128
- # => {"detected"=>false, "result"=>"clean site"}
123
+ vturl_report.report['data']['attributes']['last_analysis_results']['Avira']
124
+ # => {"category"=>"harmless", "engine_name"=>"Avira", "method"=>"blacklist", "result"=>"clean"}
129
125
  ```
130
126
 
131
- ### URL Scan
127
+ ### URL Upload
132
128
 
133
129
  ```ruby
134
130
  require 'virustotal_api'
@@ -136,27 +132,22 @@ require 'virustotal_api'
136
132
  url = 'http://www.google.com'
137
133
  api_key = 'MY_API_KEY'
138
134
 
139
- vturl_scan = VirustotalAPI::URLScan.scan(url, api_key)
135
+ vturl_scan = VirustotalAPI::URL.upload(url, api_key)
140
136
 
141
- # Scan ID of file
142
- vturl_scan.scan_id
143
- # => "dd014af5ed6b38d9130e3f466f850e46d21b951199d53a18ef29ee9341614eaf-1562751553"
137
+ # Virustotal ID of file
138
+ vturl_scan.id
139
+ # => "u-dd014af5ed6b38d9130e3f466f850e46d21b951199d53a18ef29ee9341614eaf-1598531929"
144
140
 
145
141
  # Response results are available via #response
146
142
  vturl_scan.report
147
143
  # =>
148
- {
149
- "permalink": "https://www.virustotal.com/url/dd014af5ed6b38d9130e3f466f850e46d21b951199d53a18ef29ee9341614eaf/analysis/1562751553/",
150
- "resource": "http://www.google.com/",
151
- "url": "http://www.google.com/",
152
- "response_code": 1,
153
- "scan_date": "2019-07-10 09:39:13",
154
- "scan_id": "dd014af5ed6b38d9130e3f466f850e46d21b951199d53a18ef29ee9341614eaf-1562751553",
155
- "verbose_msg": "Scan request successfully queued, come back later for the report"
156
- }
144
+ {"data"=>
145
+ {"id"=>
146
+ "u-dd014af5ed6b38d9130e3f466f850e46d21b951199d53a18ef29ee9341614eaf-1598531929",
147
+ "type"=>"analysis"}}
157
148
  ```
158
149
 
159
- ### IP Report
150
+ ### IP Find
160
151
 
161
152
  ```ruby
162
153
  require 'virustotal_api'
@@ -164,7 +155,7 @@ require 'virustotal_api'
164
155
  ip = '8.8.8.8'
165
156
  api_key = 'MY_API_KEY'
166
157
 
167
- vtip_report = VirustotalAPI::IPReport.find(ip, api_key)
158
+ vtip_report = VirustotalAPI::IP.find(ip, api_key)
168
159
 
169
160
  # Does the resource have any results?
170
161
  vtip_report.exists?
@@ -175,7 +166,7 @@ vtip_report.report
175
166
  # => Hash of report results
176
167
  ```
177
168
 
178
- ### Domain Report
169
+ ### Domain Find
179
170
 
180
171
  ```ruby
181
172
  require 'virustotal_api'
@@ -183,7 +174,7 @@ require 'virustotal_api'
183
174
  domain = 'virustotal.com'
184
175
  api_key = 'MY_API_KEY'
185
176
 
186
- vtdomain_report = VirustotalAPI::DomainReport.find(domain, api_key)
177
+ vtdomain_report = VirustotalAPI::Domain.find(domain, api_key)
187
178
 
188
179
  # Does the resource have any results?
189
180
  vtdomain_report.exists?
@@ -199,6 +190,7 @@ vtdomain_report.report
199
190
  - [@postmodern](https://github.com/postmodern)
200
191
  - [@mkunkel](https://github.com/mkunkel)
201
192
  - [@jonnynux](https://github.com/jonnynux)
193
+ - [@crondaemon](https://github.com/crondaemon/)
202
194
 
203
195
  ## Contributing
204
196
 
@@ -1,11 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'virustotal_api/domain_report'
4
- require 'virustotal_api/file_report'
5
- require 'virustotal_api/file_rescan'
6
- require 'virustotal_api/file_scan'
7
- require 'virustotal_api/ip_report'
8
- require 'virustotal_api/url_report'
9
- require 'virustotal_api/url_scan'
3
+ require 'virustotal_api/analysis'
4
+ require 'virustotal_api/domain'
5
+ require 'virustotal_api/file'
6
+ require 'virustotal_api/ip'
7
+ require 'virustotal_api/url'
10
8
  require 'virustotal_api/uri'
11
9
  require 'virustotal_api/version'
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module VirustotalAPI
6
+ # A class for '/analyses' API
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
+ # @param [String] id The Virustotal ID to get the report for.
16
+ # @param [String] api_key The key for virustotal
17
+ # @return [VirustotalAPI::IP] Report
18
+ def self.find(id, api_key)
19
+ report = perform("/analyses/#{id}", api_key)
20
+ new(report)
21
+ end
22
+ end
23
+ end
24
+ # rubocop:enable Lint/MissingSuper
@@ -3,22 +3,44 @@
3
3
  require 'virustotal_api/exceptions'
4
4
  require 'rest-client'
5
5
  require 'json'
6
+ require 'base64'
6
7
 
8
+ # The base VirustotalAPI module.
7
9
  module VirustotalAPI
10
+ # The base class implementing the raw calls to Virustotal API V3.
8
11
  class Base
12
+ attr_reader :report
13
+
14
+ def initialize(report)
15
+ @report = report
16
+ end
17
+
9
18
  # @return [String] string of API URI class method
10
19
  def self.api_uri
11
20
  VirustotalAPI::URI
12
21
  end
13
22
 
14
- # @param [RestClient::Response] response
15
- # @return [Hash] the parsed JSON.
16
- def self.parse(response)
17
- if response.code == 204
18
- raise(RateLimitError, 'maximum number of 4 requests per minute reached')
19
- end
20
-
23
+ # The actual method performing a call to Virustotal
24
+ #
25
+ # @param [String] url The url of the API
26
+ # @param [String] api_key The key for virustotal
27
+ # @param [String] method The HTTP method to use
28
+ # @param [Hash] options Options to pass as payload
29
+ # @return [VirustotalAPI::Domain] Report Search Result
30
+ def self.perform(url, api_key, method = :get, options = {})
31
+ response = RestClient::Request.execute(
32
+ method: method,
33
+ url: api_uri + url,
34
+ headers: { 'x-apikey': api_key },
35
+ payload: options
36
+ )
21
37
  JSON.parse(response.body)
38
+ rescue RestClient::NotFound
39
+ nil
40
+ rescue RestClient::Unauthorized
41
+ # Raise a custom exception not to expose the underlying
42
+ # HTTP client.
43
+ raise VirustotalAPI::Unauthorized
22
44
  end
23
45
 
24
46
  # @return [String] string of API URI instance method
@@ -27,11 +49,14 @@ module VirustotalAPI
27
49
  end
28
50
 
29
51
  # @return [Boolean] if report for resource exists
30
- # 0 => not_present, 1 => exists, -1 => invalid_ip_address
31
52
  def exists?
32
- response_code = report.fetch('response_code') { nil }
53
+ !report.empty?
54
+ end
33
55
 
34
- response_code == 1
56
+ # Generate a URL identifier.
57
+ # @see https://developers.virustotal.com/v3.0/reference#url
58
+ def self.url_identifier(url)
59
+ Base64.encode64(url).strip.gsub('=', '')
35
60
  end
36
61
  end
37
62
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module VirustotalAPI
6
+ # A class for '/domains' API
7
+ class Domain < Base
8
+ # rubocop:disable Lint/UselessMethodDefinition
9
+ def initialize(report)
10
+ super(report)
11
+ end
12
+
13
+ # Find a domain.
14
+ #
15
+ # @param [String] domain The domain to search
16
+ # @param [String] api_key for virustotal
17
+ # @return [VirustotalAPI::Domain] Report Search Result
18
+ def self.find(domain, api_key)
19
+ report = perform("/domains/#{domain}", api_key)
20
+ new(report)
21
+ end
22
+ end
23
+ end
24
+ # rubocop:enable Lint/UselessMethodDefinition