virustotal_api 0.4.1 → 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) 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 +27 -2
  6. data/README.md +94 -56
  7. data/lib/virustotal_api.rb +7 -7
  8. data/lib/virustotal_api/analysis.rb +16 -0
  9. data/lib/virustotal_api/base.rb +41 -10
  10. data/lib/virustotal_api/domain.rb +18 -0
  11. data/lib/virustotal_api/exceptions.rb +3 -0
  12. data/lib/virustotal_api/file.rb +48 -0
  13. data/lib/virustotal_api/group.rb +18 -0
  14. data/lib/virustotal_api/ip.rb +18 -0
  15. data/lib/virustotal_api/uri.rb +2 -1
  16. data/lib/virustotal_api/url.rb +38 -0
  17. data/lib/virustotal_api/user.rb +18 -0
  18. data/lib/virustotal_api/version.rb +2 -1
  19. data/test/analysis_test.rb +26 -0
  20. data/test/base_test.rb +18 -23
  21. data/test/domain_test.rb +27 -0
  22. data/test/exceptions_test.rb +22 -0
  23. data/test/file_test.rb +63 -0
  24. data/test/fixtures/analysis.yml +544 -0
  25. data/test/fixtures/domain.yml +830 -0
  26. data/test/fixtures/domain_bad_request.yml +52 -0
  27. data/test/fixtures/file_analyse.yml +52 -0
  28. data/test/fixtures/file_find.yml +853 -0
  29. data/test/fixtures/file_not_found.yml +52 -0
  30. data/test/fixtures/file_rate_limit.yml +52 -0
  31. data/test/fixtures/file_unauthorized.yml +51 -0
  32. data/test/fixtures/file_upload.yml +54 -0
  33. data/test/fixtures/group_find.yml +216 -0
  34. data/test/fixtures/ip.yml +716 -0
  35. data/test/fixtures/unscanned_url_find.yml +44 -0
  36. data/test/fixtures/url_analyse.yml +52 -0
  37. data/test/fixtures/url_find.yml +599 -0
  38. data/test/fixtures/user_find.yml +213 -0
  39. data/test/group_test.rb +27 -0
  40. data/test/{ip_report_test.rb → ip_test.rb} +6 -4
  41. data/test/uri_test.rb +1 -1
  42. data/test/url_test.rb +47 -0
  43. data/test/user_test.rb +26 -0
  44. data/test/version_test.rb +1 -1
  45. data/virustotal_api.gemspec +10 -8
  46. metadata +102 -71
  47. data/.circleci/config.yml +0 -23
  48. data/.github/workflows/gem_publish.yml +0 -38
  49. data/lib/virustotal_api/domain_report.rb +0 -36
  50. data/lib/virustotal_api/file_report.rb +0 -37
  51. data/lib/virustotal_api/file_rescan.rb +0 -36
  52. data/lib/virustotal_api/file_scan.rb +0 -38
  53. data/lib/virustotal_api/ip_report.rb +0 -36
  54. data/lib/virustotal_api/url_report.rb +0 -41
  55. data/lib/virustotal_api/url_scan.rb +0 -36
  56. data/test/domain_report_test.rb +0 -32
  57. data/test/file_report_test.rb +0 -36
  58. data/test/file_rescan_test.rb +0 -32
  59. data/test/file_scan_test.rb +0 -30
  60. data/test/fixtures/domain_report.yml +0 -311
  61. data/test/fixtures/ip_report.yml +0 -1323
  62. data/test/fixtures/queue_unscanned_url_report.yml +0 -46
  63. data/test/fixtures/report.yml +0 -110
  64. data/test/fixtures/report_not_found.yml +0 -42
  65. data/test/fixtures/request_forbidden.yml +0 -38
  66. data/test/fixtures/rescan.yml +0 -47
  67. data/test/fixtures/scan.yml +0 -49
  68. data/test/fixtures/unscanned_url_report.yml +0 -43
  69. data/test/fixtures/url_report.yml +0 -95
  70. data/test/fixtures/url_scan.yml +0 -48
  71. data/test/url_report_test.rb +0 -57
  72. data/test/url_scan_test.rb +0 -30
@@ -1,23 +0,0 @@
1
- version: 2
2
- jobs:
3
- test:
4
- docker:
5
- - image: circleci/ruby:2.5.3-stretch
6
- steps:
7
- - checkout
8
- - run:
9
- name: Setup
10
- command: |
11
- gem update bundler
12
- bundle install
13
- - run:
14
- name: Rubocop
15
- command: bundle exec rake rubocop
16
- - run:
17
- name: Run Tests
18
- command: bundle exec rake test
19
- workflows:
20
- version: 2
21
- test:
22
- jobs:
23
- - test
@@ -1,38 +0,0 @@
1
- name: Ruby Gem
2
-
3
- on: release
4
-
5
- jobs:
6
- build:
7
- name: Build + Publish
8
- runs-on: ubuntu-latest
9
-
10
- steps:
11
- - uses: actions/checkout@master
12
- - name: Set up Ruby 2.6
13
- uses: actions/setup-ruby@v1
14
- with:
15
- version: 2.6.x
16
-
17
- - name: Publish to GPR
18
- run: |
19
- mkdir -p $HOME/.gem
20
- touch $HOME/.gem/credentials
21
- chmod 0600 $HOME/.gem/credentials
22
- printf -- "---\n:github: Bearer ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
23
- gem build *.gemspec
24
- gem push --KEY github --host https://rubygems.pkg.github.com/${OWNER} *.gem
25
- env:
26
- GEM_HOST_API_KEY: ${{secrets.GITHUB_TOKEN}}
27
- OWNER: username
28
-
29
- - name: Publish to RubyGems
30
- run: |
31
- mkdir -p $HOME/.gem
32
- touch $HOME/.gem/credentials
33
- chmod 0600 $HOME/.gem/credentials
34
- printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
35
- gem build *.gemspec
36
- gem push *.gem
37
- env:
38
- GEM_HOST_API_KEY: ${{secrets.RUBYGEMS_AUTH_TOKEN}}
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base'
4
-
5
- module VirustotalAPI
6
- class DomainReport < Base
7
- attr_reader :report
8
-
9
- def initialize(report)
10
- @report = report
11
- end
12
-
13
- # @param [String] domain
14
- # @param [String] api_key for virustotal
15
- # @return [VirustotalAPI::IPReport] Report Search Result
16
- def self.find(domain, api_key)
17
- response = RestClient.get(
18
- api_uri + '/domain/report',
19
- { params: params(domain, api_key) }
20
- )
21
- report = parse(response)
22
-
23
- new(report)
24
- end
25
-
26
- # @param [String] domain
27
- # @param [String] api_key virustotal
28
- # @return [Hash] params for GET Request
29
- def self.params(domain, api_key)
30
- {
31
- domain: domain,
32
- apikey: api_key
33
- }
34
- end
35
- end
36
- end
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base'
4
-
5
- module VirustotalAPI
6
- class FileReport < Base
7
- attr_reader :report, :report_url
8
-
9
- def initialize(report)
10
- @report = report
11
- @report_url = report.fetch('permalink') { nil }
12
- end
13
-
14
- # @param [String] resource file as a md5/sha1/sha256 hash
15
- # @param [String] api_key for virustotal
16
- # @return [VirustotalAPI::FileReport] Report Search Result
17
- def self.find(resource, api_key)
18
- response = RestClient.post(
19
- api_uri + '/file/report',
20
- params(resource, api_key)
21
- )
22
- report = parse(response)
23
-
24
- new(report)
25
- end
26
-
27
- # @param [String] resource file as a md5/sha1/sha256 hash
28
- # @param [String] api_key for virustotal
29
- # @return [Hash] params for POST Request
30
- def self.params(resource, api_key)
31
- {
32
- resource: resource,
33
- apikey: api_key
34
- }
35
- end
36
- end
37
- end
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base'
4
-
5
- module VirustotalAPI
6
- class FileRescan < Base
7
- attr_reader :report, :rescan_id
8
-
9
- def initialize(report)
10
- @report = report
11
- @rescan_id = @report.fetch('scan_id') { nil }
12
- end
13
-
14
- # @param [String] resource file as a md5/sha1/sha256 hash
15
- # @param [String] api_key for virustotal
16
- # @return [VirustotalAPI::FileRescan] Report
17
- def self.rescan(resource, api_key)
18
- response = RestClient.post(
19
- api_uri + '/file/rescan',
20
- apikey: api_key,
21
- resource: resource
22
- )
23
- report = parse(response)
24
-
25
- new(report)
26
- end
27
-
28
- # @return [Boolean] if file was queued
29
- # 0 => not_present, 1 => exists, -2 => queued_for_analysis
30
- def queued_for_analysis?
31
- response_code = @report.fetch('response_code') { nil }
32
-
33
- response_code == -2
34
- end
35
- end
36
- end
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base'
4
-
5
- module VirustotalAPI
6
- class FileScan < Base
7
- attr_reader :report, :scan_id
8
-
9
- def initialize(report)
10
- @report = report
11
- @scan_id = @report.fetch('scan_id') { nil }
12
- end
13
-
14
- # @param [String] file_path for file to be sent for scan
15
- # @param [String] api_key for virustotal
16
- # @param [Hash] opts hash for additional options
17
- # @return [VirusotalAPI::FileScan] Report
18
- def self.scan(file_path, api_key, opts = {})
19
- response = RestClient.post(
20
- api_uri + '/file/scan',
21
- apikey: api_key,
22
- filename: opts.fetch('filename') { File.basename(file_path) },
23
- file: File.open(file_path, 'r')
24
- )
25
- report = parse(response)
26
-
27
- new(report)
28
- end
29
-
30
- # @return [Boolean] if file was queued
31
- # 0 => not_present, 1 => exists, -2 => queued_for_analysis
32
- def queued_for_analysis?
33
- response_code = @report.fetch('response_code') { nil }
34
-
35
- response_code == -2
36
- end
37
- end
38
- end
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base'
4
-
5
- module VirustotalAPI
6
- class IPReport < Base
7
- attr_reader :report
8
-
9
- def initialize(report)
10
- @report = report
11
- end
12
-
13
- # @param [String] ip address IPv4 format
14
- # @param [String] api_key for virustotal
15
- # @return [VirustotalAPI::IPReport] Report Search Result
16
- def self.find(ip, api_key)
17
- response = RestClient.get(
18
- api_uri + '/ip-address/report',
19
- { params: params(ip, api_key) }
20
- )
21
- report = parse(response)
22
-
23
- new(report)
24
- end
25
-
26
- # @param [String] ip address IPv4 format
27
- # @param [String] api_key for virustotal
28
- # @return [Hash] params for GET Request
29
- def self.params(ip, api_key)
30
- {
31
- ip: ip,
32
- apikey: api_key
33
- }
34
- end
35
- end
36
- end
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base'
4
-
5
- module VirustotalAPI
6
- class URLReport < Base
7
- attr_reader :report, :report_url, :scan_id
8
-
9
- def initialize(report)
10
- @report = report
11
- @report_url = report.fetch('permalink') { nil }
12
- @scan_id = report.fetch('scan_id') { nil }
13
- end
14
-
15
- # @param [String] resource as an ip/domain/url
16
- # @param [String] api_key for virustotal
17
- # @param [Integer] optional param to start scan if not found. 1 for true
18
- # @return [VirustotalAPI::URLReport] Report Search Result
19
- def self.find(resource, api_key, scan = 0)
20
- response = RestClient.post(
21
- api_uri + '/url/report',
22
- params(resource, api_key, scan)
23
- )
24
- report = parse(response)
25
-
26
- new(report)
27
- end
28
-
29
- # @param [String] resource as an ip/domain/url
30
- # @param [String] api_key for virustotal
31
- # @param [Integer] optional param to start scan if not found. 1 for true
32
- # @return [Hash] params for POST Request
33
- def self.params(resource, api_key, scan = 0)
34
- {
35
- resource: resource,
36
- apikey: api_key,
37
- scan: scan.to_s
38
- }
39
- end
40
- end
41
- end
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base'
4
-
5
- module VirustotalAPI
6
- class URLScan < Base
7
- attr_reader :report, :scan_id
8
-
9
- def initialize(report)
10
- @report = report
11
- @scan_id = @report.fetch('scan_id') { nil }
12
- end
13
-
14
- # @param [String] url
15
- # @param [String] api_key for virustotal
16
- # @return [VirustotalAPI::URLScan] Report
17
- def self.scan(url, api_key)
18
- response = RestClient.post(
19
- api_uri + '/url/scan',
20
- apikey: api_key,
21
- url: url
22
- )
23
- report = parse(response)
24
-
25
- new(report)
26
- end
27
-
28
- # @return [Boolean] if file was queued
29
- # 0 => not_present, 1 => exists, -2 => queued_for_analysis
30
- def queued_for_analysis?
31
- response_code = @report.fetch('response_code') { nil }
32
-
33
- response_code == -2
34
- end
35
- end
36
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require './test/test_helper'
4
-
5
- class VirustotalAPIDomainReportTest < Minitest::Test
6
- def setup
7
- @domain = 'virustotal.com'
8
- @api_key = 'testapikey'
9
- end
10
-
11
- def test_class_exists
12
- assert VirustotalAPI::DomainReport
13
- end
14
-
15
- def test_report_response
16
- VCR.use_cassette('domain_report') do
17
- vtdomain_report = VirustotalAPI::DomainReport.find(@domain, @api_key)
18
-
19
- # Make sure that the JSON was parsed
20
- assert vtdomain_report.is_a?(VirustotalAPI::DomainReport)
21
- assert vtdomain_report.report.is_a?(Hash)
22
- end
23
- end
24
-
25
- def test_exists?
26
- VCR.use_cassette('domain_report') do
27
- vtdomain_report = VirustotalAPI::DomainReport.find(@domain, @api_key)
28
-
29
- assert vtdomain_report.exists?, true
30
- end
31
- end
32
- end
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require './test/test_helper'
4
-
5
- class VirustotalAPIFileReportTest < Minitest::Test
6
- # rubocop:disable LineLength
7
- def setup
8
- @sha256 = '01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b'
9
- @api_key = 'testapikey'
10
- end
11
-
12
- def test_class_exists
13
- assert VirustotalAPI::FileReport
14
- end
15
-
16
- def test_report_response
17
- VCR.use_cassette('report') do
18
- virustotal_report = VirustotalAPI::FileReport.find(@sha256, @api_key)
19
-
20
- # Make sure that the JSON was parsed
21
- assert virustotal_report.is_a?(VirustotalAPI::FileReport)
22
- assert virustotal_report.report.is_a?(Hash)
23
- end
24
- end
25
-
26
- def test_report_url
27
- permalink = 'https://www.virustotal.com/file/01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b/analysis/1418032127/'
28
- VCR.use_cassette('report') do
29
- virustotal_report = VirustotalAPI::FileReport.find(@sha256, @api_key)
30
-
31
- assert virustotal_report.report_url.is_a?(String)
32
- assert virustotal_report.report_url, permalink
33
- end
34
- end
35
- # rubocop:enable LineLength
36
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require './test/test_helper'
4
-
5
- class VirustotalAPIFileRescanTest < Minitest::Test
6
- # rubocop:disable LineLength
7
- def setup
8
- @sha256 = '01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b'
9
- @api_key = 'testapikey'
10
- end
11
-
12
- def test_class_exists
13
- assert VirustotalAPI::FileRescan
14
- end
15
-
16
- def test_rescan_response
17
- VCR.use_cassette('rescan') do
18
- virustotal_rescan = VirustotalAPI::FileRescan.rescan(@sha256, @api_key)
19
-
20
- assert virustotal_rescan.report.is_a?(Hash)
21
- end
22
- end
23
-
24
- def test_rescan_id
25
- VCR.use_cassette('rescan') do
26
- virustotal_rescan = VirustotalAPI::FileRescan.rescan(@sha256, @api_key)
27
-
28
- assert virustotal_rescan.rescan_id.is_a?(String)
29
- end
30
- end
31
- # rubocop:enable LineLength
32
- end
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require './test/test_helper'
4
-
5
- class VirustotalAPIFileScanTest < Minitest::Test
6
- def setup
7
- @file_path = File.expand_path('test/fixtures/null_file')
8
- @api_key = 'testapikey'
9
- end
10
-
11
- def test_class_exists
12
- assert VirustotalAPI::FileScan
13
- end
14
-
15
- def test_response
16
- VCR.use_cassette('scan') do
17
- virustotal_scan = VirustotalAPI::FileScan.scan(@file_path, @api_key)
18
-
19
- assert virustotal_scan.report.is_a?(Hash)
20
- end
21
- end
22
-
23
- def test_scan_id
24
- VCR.use_cassette('scan') do
25
- virustotal_scan = VirustotalAPI::FileScan.scan(@file_path, @api_key)
26
-
27
- assert virustotal_scan.scan_id.is_a?(String)
28
- end
29
- end
30
- end