ddr-antivirus 2.1.1 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
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