ddr-antivirus 2.1.1 → 2.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 1e2dc2816bc43d784563002fecfa27809184e0e7
4
- data.tar.gz: f662098335165f8b839dde9af1540901fbcb412e
2
+ SHA256:
3
+ metadata.gz: 5004e827b8e72a4bad210f59e100daa8bc8ee87c7f02778c1507eac15ea97b8f
4
+ data.tar.gz: 302cc664882883e7830664df63f0c21caec065dcf98d116ad8f42c102f659525
5
5
  SHA512:
6
- metadata.gz: 296903f26f411e4638f61a27782b5a6f2fd5c4d654d0c5edec1bfab8de6846c8fdd0156efdd5d302bd85135d31c7f097fd9c679bcc706e394ee740460f3812cd
7
- data.tar.gz: d88a0465de7c6d7de55827de7b8264ba808ca3e1d1ec9ad5f28e5b728de9a2771d19b706ce5945d0084f0a989f3c84893d27786c35e422b3996cdefc51815eb2
6
+ metadata.gz: 341b67b0bbe4678f02beb2cf5d10bfe7186c3a46aeaa1fa2b1beac6fa8bdcf33a3c0a5010bd9c90121f0b58ac09040c49191e12b88ed709a9042b3b59866b563
7
+ data.tar.gz: ce3fc8405d17441a81856fcb80f946e76dffcaae7570edb59c55873f8639da924b8a9d350a53f08cf6c9c72d06049dc458ff2801d2aaf0a99df36efc2f03b40b
@@ -0,0 +1,29 @@
1
+ ARG RUBY_VERSION
2
+ FROM ruby:${RUBY_VERSION}
3
+
4
+ ARG APPUSER=appuser
5
+ ARG APPGROUP=root
6
+ ARG APPROOT=/usr/src/app
7
+
8
+ RUN apt-get -y update \
9
+ && apt-get -y install \
10
+ clamdscan \
11
+ less \
12
+ vim \
13
+ wait-for-it
14
+
15
+ WORKDIR /usr/src/app
16
+ COPY . .
17
+ RUN gem install bundler -N \
18
+ && bundle install
19
+
20
+ COPY .docker/clamd.conf /etc/clamav/
21
+ COPY .docker/docker-entrypoint.sh /usr/bin/
22
+ RUN chmod +x /usr/bin/docker-entrypoint.sh
23
+
24
+ RUN groupadd -r -f $APPGROUP \
25
+ && useradd -m -r -g $APPGROUP $APPUSER
26
+
27
+ USER $APPUSER
28
+ ENTRYPOINT ["docker-entrypoint.sh"]
29
+ CMD ["bundle", "exec", "rake"]
@@ -0,0 +1,2 @@
1
+ TCPSocket 3310
2
+ TCPAddr clamav
@@ -0,0 +1,15 @@
1
+ version: '3.7'
2
+
3
+ services:
4
+ app:
5
+ image: ddr-antivirus-ruby-${RUBY_VERSION}
6
+ build:
7
+ context: ..
8
+ dockerfile: .docker/Dockerfile
9
+ args:
10
+ - RUBY_VERSION
11
+ depends_on:
12
+ - clamav
13
+
14
+ clamav:
15
+ image: gitlab-registry.oit.duke.edu/dul-its/clamav-docker:latest
@@ -0,0 +1,2 @@
1
+ #!/bin/bash
2
+ wait-for-it clamav:3310 -t 60 -- "$@"
@@ -0,0 +1,4 @@
1
+ .docker/*
2
+ !.docker/clamd.conf
3
+ !.docker/docker-entrypoint.sh
4
+ .gitlab-ci.yml
@@ -0,0 +1,30 @@
1
+ stages:
2
+ - build
3
+
4
+ variables:
5
+ COMPOSE_FILE: .docker/docker-compose.yml
6
+
7
+ .build_app_template: &build_app_def
8
+ stage: build
9
+ before_script:
10
+ - docker --version
11
+ - docker-compose --version
12
+ script:
13
+ - docker-compose up --build --exit-code-from app
14
+ after_script:
15
+ - docker-compose down
16
+
17
+ build_app_ruby24:
18
+ <<: *build_app_def
19
+ variables:
20
+ RUBY_VERSION: '2.4'
21
+
22
+ build_app_ruby25:
23
+ <<: *build_app_def
24
+ variables:
25
+ RUBY_VERSION: '2.5'
26
+
27
+ build_app_ruby26:
28
+ <<: *build_app_def
29
+ variables:
30
+ RUBY_VERSION: '2.6'
data/README.md CHANGED
@@ -2,9 +2,6 @@
2
2
 
3
3
  Pluggable antivirus service for Ruby applications.
4
4
 
5
- [![Gem Version](https://badge.fury.io/rb/ddr-antivirus.svg)](http://badge.fury.io/rb/ddr-antivirus)
6
- [![Build Status](https://travis-ci.org/duke-libraries/ddr-antivirus.svg?branch=develop)](https://travis-ci.org/duke-libraries/ddr-antivirus)
7
-
8
5
  ## Installation
9
6
 
10
7
  Add this line to your application's Gemfile:
@@ -31,22 +28,12 @@ Ddr::Antivirus.scanner do |scanner|
31
28
  end
32
29
  ```
33
30
 
34
- ### Exceptions
35
-
36
- All exceptions under the `Ddr::Antivirus` namespace.
37
-
38
- `Error` - Parent exception class.
39
-
40
- `VirusFoundError` - A virus was found. The message includes the original output from the scanner.
41
-
42
- `ScannerError` - The scanner encountered an error (e.g., error exit status).
43
-
44
31
  ### Example
45
32
 
46
33
  ```
47
34
  > require 'ddr/antivirus'
48
35
  => true
49
-
36
+
50
37
  > Ddr::Antivirus.scanner_adapter = :clamd
51
38
  => :clamd
52
39
 
@@ -74,7 +61,7 @@ Time: 0.001 sec (0 m 0 s)
74
61
 
75
62
  ### Logging
76
63
 
77
- In a Rails application, `Ddr::Antivirus` will log messages to the Rails logger by default. The fallback logger writes to STDERR. You may also explicitly set `Ddr::Antivirus.logger` to any object that supports the Ruby logger API:
64
+ In a Rails application, `Ddr::Antivirus` will log messages to the Rails logger by default. The fallback logger writes to `STDERR`. You may also explicitly set `Ddr::Antivirus.logger` to any object that supports the Ruby logger API:
78
65
 
79
66
  ```ruby
80
67
  require "logger"
@@ -18,7 +18,8 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_development_dependency "bundler", "~> 1.6"
21
+ spec.add_development_dependency "bundler"
22
22
  spec.add_development_dependency "rake"
23
23
  spec.add_development_dependency "rspec", "~> 3.0"
24
+ spec.add_development_dependency "rspec-its"
24
25
  end
@@ -1,6 +1,7 @@
1
1
  require "logger"
2
2
 
3
3
  require_relative "antivirus/version"
4
+ require_relative "antivirus/exceptions"
4
5
  require_relative "antivirus/scanner"
5
6
  require_relative "antivirus/scan_result"
6
7
  require_relative "antivirus/scanner_adapter"
@@ -9,20 +10,6 @@ require_relative "antivirus/adapters/null_scanner_adapter"
9
10
  module Ddr
10
11
  module Antivirus
11
12
 
12
- class Error < ::StandardError; end
13
-
14
- class ResultError < Error
15
- attr_reader :result
16
- def initialize(result)
17
- super(result.to_s)
18
- @result = result
19
- end
20
- end
21
-
22
- class VirusFoundError < ResultError; end
23
-
24
- class ScannerError < ResultError; end
25
-
26
13
  class << self
27
14
  attr_accessor :logger, :scanner_adapter
28
15
 
@@ -26,6 +26,7 @@ module Ddr::Antivirus
26
26
  end
27
27
 
28
28
  def clamdscan(path)
29
+ check_file_size(path) if max_file_size
29
30
  output = make_readable(path) do
30
31
  command "--fdpass", safe_path(path)
31
32
  end
@@ -37,17 +38,26 @@ module Ddr::Antivirus
37
38
  end
38
39
 
39
40
  def config
40
- @config ||= `#{CONFIG}`
41
+ # If client and server are on separate hosts
42
+ # attempt to read config may raise an exception.
43
+ @config ||= `#{CONFIG}` rescue nil
41
44
  end
42
45
 
43
46
  def max_file_size
44
47
  if m = MAX_FILE_SIZE_RE.match(config)
45
- m[1]
48
+ m[1].to_i
46
49
  end
47
50
  end
48
51
 
49
52
  private
50
53
 
54
+ def check_file_size(path)
55
+ if (file_size = File.size(path)) > max_file_size
56
+ raise MaxFileSizeExceeded, "Unable to scan file \"#{path}\" because size (#{file_size})" \
57
+ " exceeds clamconf MaxFileSize (#{max_file_size})."
58
+ end
59
+ end
60
+
51
61
  def command(*args)
52
62
  cmd = args.dup.unshift(SCANNER).join(" ")
53
63
  `#{cmd}`
@@ -0,0 +1,19 @@
1
+ module Ddr::Antivirus
2
+
3
+ class Error < ::StandardError; end
4
+
5
+ class MaxFileSizeExceeded < Error; end
6
+
7
+ class ResultError < Error
8
+ attr_reader :result
9
+ def initialize(result)
10
+ super(result.to_s)
11
+ @result = result
12
+ end
13
+ end
14
+
15
+ class VirusFoundError < ResultError; end
16
+
17
+ class ScannerError < ResultError; end
18
+
19
+ end
@@ -9,16 +9,11 @@ module Ddr::Antivirus
9
9
  # Scan a file path for viruses.
10
10
  #
11
11
  # @param path [String] file path to scan.
12
- # @return [Ddr::Antivirus::Adapters::ScanResult] the result of the scan.
12
+ # @return [Ddr::Antivirus::ScanResult] the result of the scan.
13
13
  def scan(path)
14
14
  raise NotImplementedError, "Adapters must implement the `scan' method."
15
15
  end
16
16
 
17
- # Return the adapter configuration options
18
- def config
19
- Ddr::Antivirus.adapter_config
20
- end
21
-
22
17
  private
23
18
 
24
19
  def logger
@@ -1,5 +1,5 @@
1
1
  module Ddr
2
2
  module Antivirus
3
- VERSION = "2.1.1"
3
+ VERSION = "2.2.0"
4
4
  end
5
5
  end
@@ -2,6 +2,8 @@ require 'ddr/antivirus'
2
2
 
3
3
  Ddr::Antivirus.test_mode!
4
4
 
5
+ require 'rspec/its'
6
+
5
7
  RSpec.configure do |config|
6
8
  # The settings below are suggested to provide a good initial experience
7
9
  # with RSpec, but feel free to customize to your heart's content.
@@ -7,56 +7,104 @@ module Ddr::Antivirus
7
7
 
8
8
  before do
9
9
  allow(subject).to receive(:version) { "version" }
10
+ allow(subject).to receive(:config) do
11
+ <<-EOS
12
+ MaxScanSize = "104857600"
13
+ MaxFileSize = "26214400"
14
+ MaxRecursion = "16"
15
+ MaxFiles = "10000"
16
+ EOS
17
+ end
10
18
  end
11
19
 
12
- describe "permissions" do
13
- before do
14
- @file = Tempfile.new("test")
15
- @file.write("Scan me!")
16
- @file.close
17
- FileUtils.chmod(0000, @file.path)
18
- end
19
- after { @file.unlink }
20
- describe "when the file is not readable" do
21
- it "scans the file" do
22
- expect { subject.scan(@file.path) }.not_to raise_error
20
+ its(:max_file_size) { is_expected.to eq(26214400) }
21
+
22
+ describe "#scan" do
23
+ describe "file size" do
24
+ let(:path) { File.expand_path(File.join("..", "..", "fixtures", "blue-devil.png"), __FILE__) }
25
+ describe "when max file size is not set or unknown" do
26
+ before do
27
+ allow(subject).to receive(:max_file_size) { nil }
28
+ end
29
+ it "scans the file" do
30
+ expect { subject.scan(path) }.not_to raise_error
31
+ end
32
+ end
33
+ describe "when max file size is greater than the size of the file to be scanned" do
34
+ before do
35
+ allow(subject).to receive(:max_file_size) { File.size(path) + 1 }
36
+ end
37
+ it "scans the file" do
38
+ expect { subject.scan(path) }.not_to raise_error
39
+ end
40
+ end
41
+ describe "when max file size is equal to the size of the file to be scanned" do
42
+ before do
43
+ allow(subject).to receive(:max_file_size) { File.size(path) }
44
+ end
45
+ it "scans the file" do
46
+ expect { subject.scan(path) }.not_to raise_error
47
+ end
23
48
  end
24
- it "resets the original permissions" do
25
- expect { subject.scan(@file.path) }.not_to change { File.stat(@file.path).mode }
49
+ describe "when max file size is less than the size of the file to be scanned" do
50
+ before do
51
+ allow(subject).to receive(:max_file_size) { File.size(path) - 1 }
52
+ end
53
+ it "raises an exception" do
54
+ expect { subject.scan(path) }.to raise_error(MaxFileSizeExceeded)
55
+ end
26
56
  end
27
57
  end
28
- end
29
58
 
30
- describe "result" do
31
- let(:path) { File.expand_path(File.join("..", "..", "fixtures", "blue-devil.png"), __FILE__) }
32
- before do
33
- allow(subject).to receive(:clamdscan).with(path) { ["output", exitcode] }
34
- end
35
- describe "when a virus is found" do
36
- let(:exitcode) { 1 }
37
- it "should raise a VirusFoundError" do
38
- expect { subject.scan(path) }.to raise_error(VirusFoundError)
59
+ describe "permissions" do
60
+ before do
61
+ @file = Tempfile.new("test")
62
+ @file.write("Scan me!")
63
+ @file.close
64
+ FileUtils.chmod(0000, @file.path)
39
65
  end
40
- end
41
- describe "when there is an error" do
42
- let(:exitcode) { 2 }
43
- it "raises a ScannerError" do
44
- expect { subject.scan(path) }.to raise_error(ScannerError)
66
+ after { @file.unlink }
67
+ describe "when the file is not readable" do
68
+ it "scans the file" do
69
+ expect { subject.scan(@file.path) }.not_to raise_error
70
+ end
71
+ it "resets the original permissions" do
72
+ expect { subject.scan(@file.path) }.not_to change { File.stat(@file.path).mode }
73
+ end
45
74
  end
46
75
  end
47
- describe "success" do
48
- let(:exitcode) { 0 }
49
- it "has output" do
50
- expect(subject.scan(path).output).to eq("output")
76
+
77
+ describe "result" do
78
+ let(:path) { File.expand_path(File.join("..", "..", "fixtures", "blue-devil.png"), __FILE__) }
79
+ before do
80
+ allow(subject).to receive(:clamdscan).with(path) { ["output", exitcode] }
51
81
  end
52
- it "has a scanned_at time" do
53
- expect(subject.scan(path).scanned_at).to be_a(Time)
82
+ describe "when a virus is found" do
83
+ let(:exitcode) { 1 }
84
+ it "should raise a VirusFoundError" do
85
+ expect { subject.scan(path) }.to raise_error(VirusFoundError)
86
+ end
54
87
  end
55
- it "has a version" do
56
- expect(subject.scan(path).version).to eq("version")
88
+ describe "when there is an error" do
89
+ let(:exitcode) { 2 }
90
+ it "raises a ScannerError" do
91
+ expect { subject.scan(path) }.to raise_error(ScannerError)
92
+ end
57
93
  end
58
- it "has the file_path" do
59
- expect(subject.scan(path).file_path).to eq(path)
94
+ describe "success" do
95
+ let(:exitcode) { 0 }
96
+ it "has output" do
97
+ expect(subject.scan(path).output).to eq("output")
98
+ end
99
+ it "has a scanned_at time" do
100
+ expect(subject.scan(path).scanned_at).to be_a(Time)
101
+ end
102
+ it "has a version" do
103
+ expect(subject.scan(path).version).to eq("version")
104
+ end
105
+ it "has the file_path" do
106
+ expect(subject.scan(path).file_path).to eq(path)
107
+ end
60
108
  end
61
109
  end
62
110
  end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ddr-antivirus
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Chandek-Stark
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-04 00:00:00.000000000 Z
11
+ date: 2019-08-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.6'
19
+ version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.6'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec-its
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  description: Pluggable antivirus scanning service.
56
70
  email:
57
71
  - dchandekstark@gmail.com
@@ -59,9 +73,14 @@ executables: []
59
73
  extensions: []
60
74
  extra_rdoc_files: []
61
75
  files:
76
+ - ".docker/Dockerfile"
77
+ - ".docker/clamd.conf"
78
+ - ".docker/docker-compose.yml"
79
+ - ".docker/docker-entrypoint.sh"
80
+ - ".dockerignore"
62
81
  - ".gitignore"
82
+ - ".gitlab-ci.yml"
63
83
  - ".rspec"
64
- - ".travis.yml"
65
84
  - Gemfile
66
85
  - LICENSE.txt
67
86
  - README.md
@@ -71,6 +90,7 @@ files:
71
90
  - lib/ddr/antivirus.rb
72
91
  - lib/ddr/antivirus/adapters/clamd_scanner_adapter.rb
73
92
  - lib/ddr/antivirus/adapters/null_scanner_adapter.rb
93
+ - lib/ddr/antivirus/exceptions.rb
74
94
  - lib/ddr/antivirus/scan_result.rb
75
95
  - lib/ddr/antivirus/scanner.rb
76
96
  - lib/ddr/antivirus/scanner_adapter.rb
@@ -100,7 +120,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
100
120
  version: '0'
101
121
  requirements: []
102
122
  rubyforge_project:
103
- rubygems_version: 2.4.6
123
+ rubygems_version: 2.7.9
104
124
  signing_key:
105
125
  specification_version: 4
106
126
  summary: Pluggable antivirus scanning service.
@@ -1,12 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.1.5
4
- cache:
5
- - bundler
6
- - apt
7
- before_install:
8
- - sudo apt-get update -qq
9
- - sudo apt-get install -y clamav-daemon
10
- before_script:
11
- - sudo freshclam -v
12
- - sudo /etc/init.d/clamav-daemon start