ipscriptables 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +17 -0
- data/.rubocop.yml +15 -0
- data/.travis.yml +10 -0
- data/CHANGELOG.md +6 -0
- data/CONTRIBUTING.md +43 -0
- data/Gemfile +13 -0
- data/LICENSE +20 -0
- data/README.md +54 -0
- data/Rakefile +22 -0
- data/bin/ipscriptables +6 -0
- data/cookbook/.gitignore +2 -0
- data/cookbook/.kitchen.yml +28 -0
- data/cookbook/Berksfile +6 -0
- data/cookbook/README.md +53 -0
- data/cookbook/attributes/default.rb +3 -0
- data/cookbook/chefignore +96 -0
- data/cookbook/libraries/default.rb +35 -0
- data/cookbook/metadata.rb +9 -0
- data/cookbook/providers/rules.rb +21 -0
- data/cookbook/recipes/default.rb +10 -0
- data/cookbook/recipes/load.rb +8 -0
- data/cookbook/resources/rules.rb +17 -0
- data/cookbook/test/cookbooks/ipscriptables-test/#metadata.rb# +8 -0
- data/cookbook/test/cookbooks/ipscriptables-test/metadata.rb +11 -0
- data/cookbook/test/cookbooks/ipscriptables-test/recipes/default.rb +23 -0
- data/cookbook/test/cookbooks/ipscriptables-test/recipes/prepare.rb +5 -0
- data/cookbook/test/data/.gitignore +1 -0
- data/cookbook/test/integration/default/bats/default.bats +9 -0
- data/doc/iptables-switches.txt +342 -0
- data/ipscriptables.gemspec +38 -0
- data/lib/ipscriptables.rb +14 -0
- data/lib/ipscriptables/chain.rb +83 -0
- data/lib/ipscriptables/cli.rb +19 -0
- data/lib/ipscriptables/helpers.rb +39 -0
- data/lib/ipscriptables/pretty_print.rb +58 -0
- data/lib/ipscriptables/rule.rb +95 -0
- data/lib/ipscriptables/ruleset.rb +103 -0
- data/lib/ipscriptables/ruleset/class_methods.rb +67 -0
- data/lib/ipscriptables/runtime.rb +97 -0
- data/lib/ipscriptables/table.rb +77 -0
- data/lib/ipscriptables/version.rb +5 -0
- data/spec/fixtures/clyhq.txt +40 -0
- data/spec/fixtures/docker-plus.txt +31 -0
- data/spec/fixtures/drumknott.txt +67 -0
- data/spec/fixtures/falcor.txt +39 -0
- data/spec/fixtures/ghq.txt +102 -0
- data/spec/fixtures/ip6tables-empty.txt +7 -0
- data/spec/fixtures/only-docker-c.txt +23 -0
- data/spec/fixtures/only-docker.txt +23 -0
- data/spec/fixtures/only_docker.rb +22 -0
- data/spec/fixtures/runtime.rb +7 -0
- data/spec/fixtures/runtime2.rb +16 -0
- data/spec/ipscriptables/dsl_spec.rb +74 -0
- data/spec/ipscriptables/helpers_spec.rb +58 -0
- data/spec/ipscriptables/rule_spec.rb +41 -0
- data/spec/ipscriptables/ruleset/class_methods_spec.rb +52 -0
- data/spec/ipscriptables/ruleset_spec.rb +199 -0
- data/spec/ipscriptables/runtime_spec.rb +227 -0
- data/spec/ipscriptables/table_spec.rb +32 -0
- data/spec/ipscriptables/version_spec.rb +12 -0
- data/spec/spec_helper.rb +60 -0
- metadata +350 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
# Generated by iptables-save v1.4.12 on Wed Feb 19 13:37:35 2014
|
2
|
+
*filter
|
3
|
+
:INPUT ACCEPT [211:14626]
|
4
|
+
:FORWARD ACCEPT [0:0]
|
5
|
+
:OUTPUT ACCEPT [122:11280]
|
6
|
+
[1:2] -A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
7
|
+
[1:2] -A FORWARD -i docker0 ! -o docker0 -j ACCEPT
|
8
|
+
[1:2] -A FORWARD -i docker0 -o docker0 -j ACCEPT
|
9
|
+
COMMIT
|
10
|
+
# Completed on Wed Feb 19 13:37:35 2014
|
11
|
+
# Generated by iptables-save v1.4.12 on Wed Feb 19 13:37:35 2014
|
12
|
+
*nat
|
13
|
+
:PREROUTING ACCEPT [5:1208]
|
14
|
+
:INPUT ACCEPT [5:1208]
|
15
|
+
:OUTPUT ACCEPT [42:3215]
|
16
|
+
:POSTROUTING ACCEPT [42:3215]
|
17
|
+
:DOCKER - [0:0]
|
18
|
+
[1:2] -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
|
19
|
+
[1:2] -A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
|
20
|
+
[1:2] -A POSTROUTING -s 172.17.0.0/16 ! -d 172.17.0.0/16 -j MASQUERADE
|
21
|
+
[1:2] -A POSTROUTING -s 10.0.3.0/24 ! -d 10.0.3.0/24 -j MASQUERADE
|
22
|
+
COMMIT
|
23
|
+
# Completed on Wed Feb 19 13:37:35 2014
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Generated by iptables-save v1.4.12 on Wed Feb 19 13:37:35 2014
|
2
|
+
*filter
|
3
|
+
:INPUT ACCEPT [211:14626]
|
4
|
+
:FORWARD ACCEPT [0:0]
|
5
|
+
:OUTPUT ACCEPT [122:11280]
|
6
|
+
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
7
|
+
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
|
8
|
+
-A FORWARD -i docker0 -o docker0 -j ACCEPT
|
9
|
+
COMMIT
|
10
|
+
# Completed on Wed Feb 19 13:37:35 2014
|
11
|
+
# Generated by iptables-save v1.4.12 on Wed Feb 19 13:37:35 2014
|
12
|
+
*nat
|
13
|
+
:PREROUTING ACCEPT [5:1208]
|
14
|
+
:INPUT ACCEPT [5:1208]
|
15
|
+
:OUTPUT ACCEPT [42:3215]
|
16
|
+
:POSTROUTING ACCEPT [42:3215]
|
17
|
+
:DOCKER - [0:0]
|
18
|
+
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
|
19
|
+
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
|
20
|
+
-A POSTROUTING -s 172.17.0.0/16 ! -d 172.17.0.0/16 -j MASQUERADE
|
21
|
+
-A POSTROUTING -s 10.0.3.0/24 ! -d 10.0.3.0/24 -j MASQUERADE
|
22
|
+
COMMIT
|
23
|
+
# Completed on Wed Feb 19 13:37:35 2014
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
table :filter do
|
4
|
+
chain :FORWARD do
|
5
|
+
rule '-o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT'
|
6
|
+
rule '-i docker0 ! -o docker0 -j ACCEPT'
|
7
|
+
rule '-i docker0 -o docker0 -j ACCEPT'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
table :nat do
|
12
|
+
chain :PREROUTING do
|
13
|
+
rule '-m addrtype --dst-type LOCAL -j DOCKER'
|
14
|
+
end
|
15
|
+
chain :OUTPUT do
|
16
|
+
rule '! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER'
|
17
|
+
end
|
18
|
+
chain :POSTROUTING do
|
19
|
+
rule '-s 172.17.0.0/16 ! -d 172.17.0.0/16 -j MASQUERADE'
|
20
|
+
rule '-s 10.0.3.0/24 ! -d 10.0.3.0/24 -j MASQUERADE'
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
iptables do
|
4
|
+
table :nat do
|
5
|
+
chain :PREROUTING do
|
6
|
+
rule '-m addrtype --dst-type LOCAL -j DOCKER'
|
7
|
+
end
|
8
|
+
chain :OUTPUT do
|
9
|
+
rule '! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER'
|
10
|
+
end
|
11
|
+
chain :POSTROUTING do
|
12
|
+
rule '-s 172.17.0.0/16 ! -d 172.17.0.0/16 -j MASQUERADE'
|
13
|
+
rule '-s 10.0.3.0/24 ! -d 10.0.3.0/24 -j MASQUERADE'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
module IPScriptables
|
5
|
+
describe 'Chain#rule' do
|
6
|
+
THREE_PORTS_RULES = <<EOF
|
7
|
+
*filter
|
8
|
+
:INPUT ACCEPT [0:0]
|
9
|
+
:FORWARD ACCEPT [0:0]
|
10
|
+
:OUTPUT ACCEPT [0:0]
|
11
|
+
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
|
12
|
+
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
|
13
|
+
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
|
14
|
+
-A INPUT -j REJECT --reject-with icmp-port-unreachable
|
15
|
+
COMMIT
|
16
|
+
EOF
|
17
|
+
|
18
|
+
def expect_three_ports_from(&block)
|
19
|
+
rs = Ruleset.new do
|
20
|
+
table :filter do
|
21
|
+
chain :INPUT do
|
22
|
+
instance_eval(&block)
|
23
|
+
rule '-j REJECT --reject-with icmp-port-unreachable'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
expect { rs.render == THREE_PORTS_RULES }
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'allows to describe rulesets' do
|
31
|
+
expect_three_ports_from do
|
32
|
+
rule '-p tcp -m tcp --dport 22 -j ACCEPT'
|
33
|
+
rule '-p tcp -m tcp --dport 80 -j ACCEPT'
|
34
|
+
rule '-p tcp -m tcp --dport 443 -j ACCEPT'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'Allows nesting for DRY' do
|
39
|
+
expect_three_ports_from do
|
40
|
+
rule '-p tcp -m tcp' do
|
41
|
+
rule '--dport 22 -j ACCEPT'
|
42
|
+
rule '--dport 80 -j ACCEPT'
|
43
|
+
rule '--dport 443 -j ACCEPT'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'accepts iterable of elements for iteration' do
|
49
|
+
expect_three_ports_from do
|
50
|
+
rule [
|
51
|
+
'-p tcp -m tcp --dport 22 -j ACCEPT',
|
52
|
+
'-p tcp -m tcp --dport 80 -j ACCEPT',
|
53
|
+
'-p tcp -m tcp --dport 443 -j ACCEPT'
|
54
|
+
]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'accepts multiple of arguments and processes them as if nested' do
|
59
|
+
expect_three_ports_from do
|
60
|
+
rule '-p tcp -m tcp --dport', [22, 80, 443], '-j ACCEPT'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'understands parameters provided as hashes' do
|
65
|
+
expect_three_ports_from do
|
66
|
+
rule p: :tcp, m: :tcp, dport: [22, 80, 443], j: :ACCEPT
|
67
|
+
end
|
68
|
+
|
69
|
+
expect_three_ports_from do
|
70
|
+
rule '-p' => :tcp, '-m' => :tcp, '--dport' => [22, 80, 443], '-j' => :ACCEPT # rubocop:disable LineLength
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
module IPScriptables
|
5
|
+
describe 'Helpers.run_command' do
|
6
|
+
def mock_status(success = true)
|
7
|
+
rv = mock('Process::Status')
|
8
|
+
rv.expects(:success?).at_least(0).returns(success)
|
9
|
+
rv
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'runs external command and returns its stdout' do
|
13
|
+
Helpers.expects('systemu').with(%w(echo foo))
|
14
|
+
.returns([mock_status, "foo\n", ''])
|
15
|
+
expect { Helpers.run_command('echo', 'foo') == "foo\n" }
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'raises RuntimError on failure status' do
|
19
|
+
Helpers.expects('systemu').with(%w(false))
|
20
|
+
.returns([mock_status(false), '', ''])
|
21
|
+
expect { rescuing { Helpers.run_command('false') }.is_a?(RuntimeError) }
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'prints command\'s stderr on stderr' do
|
25
|
+
Helpers.expects('systemu').with(%w(cmd))
|
26
|
+
.returns([mock_status, "bar\n", "foo\n"])
|
27
|
+
out, err = capture_io { @res = Helpers.run_command('cmd') }
|
28
|
+
expect { out == '' }
|
29
|
+
expect { err == "cmd: foo\n" }
|
30
|
+
expect { @res == "bar\n" }
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'prints stdout on stderr in case of failure' do
|
34
|
+
Helpers.expects('systemu').with(%w(cmd))
|
35
|
+
.returns([mock_status(false), "foo\n", ''])
|
36
|
+
out, err = capture_io do
|
37
|
+
@rescued = rescuing { Helpers.run_command('cmd') }
|
38
|
+
end
|
39
|
+
expect { out == '' }
|
40
|
+
expect { err == "cmd: foo\n" }
|
41
|
+
expect { @rescued.is_a?(RuntimeError) }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe 'Helpers.ohai' do
|
46
|
+
before { fauxhai! }
|
47
|
+
|
48
|
+
it 'returns a configured instance of Ohai' do
|
49
|
+
expect { Helpers.ohai['hostname'] == 'Fauxhai' }
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'caches the ohai instance for better performance' do
|
53
|
+
ohai1 = Helpers.ohai
|
54
|
+
ohai2 = Helpers.ohai
|
55
|
+
expect { ohai1.object_id == ohai2.object_id }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
module IPScriptables
|
5
|
+
describe 'Rule' do
|
6
|
+
let(:chain) do
|
7
|
+
ch = mock(Chain.name)
|
8
|
+
ch.expects(:original).at_least_once.returns(nil)
|
9
|
+
ch.expects(:opts).at_least(0).returns({})
|
10
|
+
ch
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:rule) do
|
14
|
+
Rule.new(chain, '-s 1.1.1.1/32 -p tcp -m tcp -m multiport --dports 4949,5666 -j ACCEPT') # rubocop:disable LineLength
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'allows accessing individual switches by dict access' do
|
18
|
+
expect { rule['--dports'] == '4949,5666' }
|
19
|
+
expect { rule['dports'] == '4949,5666' }
|
20
|
+
expect { rule[:dports] == '4949,5666' }
|
21
|
+
expect { rule[:destination_ports] == '4949,5666' }
|
22
|
+
expect { rule[:j] == 'ACCEPT' }
|
23
|
+
expect { rule[:jump] == 'ACCEPT' }
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'rolls multiple options into arrays' do
|
27
|
+
expect { rule[:m] == %w(tcp multiport) }
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'has convenience aliases' do
|
31
|
+
expect { rule.match == %w(tcp multiport) }
|
32
|
+
expect { rule.proto == 'tcp' }
|
33
|
+
expect { rule.target == 'ACCEPT' }
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'can be also matched by regexp' do
|
37
|
+
expect { rule =~ /multiport/ }
|
38
|
+
deny { rule =~ /udp/ }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
module IPScriptables
|
5
|
+
describe 'Ruleset.from_file, .from_s' do
|
6
|
+
Dir[fixture('**/*.txt')].each do |fixture|
|
7
|
+
it "parses #{File.basename(fixture)} and renders it back" do
|
8
|
+
fixture_text = File.open(fixture).lines.grep(/^[^#]/).join
|
9
|
+
expect { Ruleset.from_file(fixture).render == fixture_text }
|
10
|
+
expect { Ruleset.from_s(File.read(fixture)).render == fixture_text }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'fails on invalid input' do
|
15
|
+
expect { rescuing { Ruleset.from_s('Invalid!') }.is_a?(RuntimeError) }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'Ruleset.from_command' do
|
20
|
+
let(:fixture_content) { File.read(fixture('ghq.txt')) }
|
21
|
+
let(:fixture_text) { fixture_content.lines.grep(/^[^#]/).join }
|
22
|
+
|
23
|
+
it 'executes external command and parses its output as ruleset' do
|
24
|
+
Helpers.expects(:run_command)
|
25
|
+
.with('a', 'command', 'with', 'arguments')
|
26
|
+
.returns(fixture_content)
|
27
|
+
rs = Ruleset.from_command('a', 'command', 'with', 'arguments')
|
28
|
+
expect { rs.render == fixture_text }
|
29
|
+
expect { rs.command == %w(a command with arguments) }
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'has a convenience alias .from_iptables' do
|
33
|
+
Helpers.expects(:run_command)
|
34
|
+
.with('iptables-save', '-c')
|
35
|
+
.returns(fixture_content)
|
36
|
+
rs = Ruleset.from_iptables
|
37
|
+
expect { rs.render == fixture_text }
|
38
|
+
expect { rs.command == %w(iptables-save -c) }
|
39
|
+
expect { rs.family == :inet }
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'has a convenience alias .from_ip6tables' do
|
43
|
+
Helpers.expects(:run_command)
|
44
|
+
.with('ip6tables-save', '-c')
|
45
|
+
.returns(fixture_content)
|
46
|
+
rs = Ruleset.from_ip6tables
|
47
|
+
expect { rs.render == fixture_text }
|
48
|
+
expect { rs.command == %w(ip6tables-save -c) }
|
49
|
+
expect { rs.family == :inet6 }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,199 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# rubocop:disable LineLength
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
module IPScriptables
|
6
|
+
describe 'Ruleset#method_missing' do
|
7
|
+
let(:rs) { Ruleset.new(foo: 23) }
|
8
|
+
it 'forwards calls to ruleset\'s options' do
|
9
|
+
expect { rs.foo == 23 }
|
10
|
+
expect { rs.respond_to? :foo }
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'rejects methods that are not in options' do
|
14
|
+
expect { rescuing { rs.bar }.is_a?(NoMethodError) }
|
15
|
+
deny { rs.respond_to? :bar }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'Ruleset#bud' do
|
20
|
+
let(:drumknott) { Ruleset.from_file(fixture('drumknott.txt')) }
|
21
|
+
let(:ghq) { Ruleset.from_file(fixture('ghq.txt')) }
|
22
|
+
|
23
|
+
it 'creates a child ruleset with identical tables and chains, but no rules' do
|
24
|
+
expected_rules = <<-EOF
|
25
|
+
*mangle
|
26
|
+
:PREROUTING ACCEPT [9070264:2761485141]
|
27
|
+
:INPUT ACCEPT [5794:541194]
|
28
|
+
:FORWARD ACCEPT [9064470:2760943947]
|
29
|
+
:OUTPUT ACCEPT [4447:1027385]
|
30
|
+
:POSTROUTING ACCEPT [9068917:2761971332]
|
31
|
+
COMMIT
|
32
|
+
*nat
|
33
|
+
:PREROUTING ACCEPT [936831:58138468]
|
34
|
+
:INPUT ACCEPT [383149:28442596]
|
35
|
+
:OUTPUT ACCEPT [188115:19311882]
|
36
|
+
:POSTROUTING ACCEPT [88176135:5298607741]
|
37
|
+
:DOCKER - [0:0]
|
38
|
+
COMMIT
|
39
|
+
*filter
|
40
|
+
:INPUT ACCEPT [419:18560]
|
41
|
+
:FORWARD ACCEPT [5802508472:1613710597740]
|
42
|
+
:OUTPUT ACCEPT [2072879:485657573]
|
43
|
+
:FWR - [0:0]
|
44
|
+
COMMIT
|
45
|
+
EOF
|
46
|
+
child = drumknott.bud
|
47
|
+
expect { child.render == expected_rules }
|
48
|
+
expect { child.original == drumknott }
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'allows chain inheritance' do
|
52
|
+
child = drumknott.bud do
|
53
|
+
inherit :nat, :DOCKER
|
54
|
+
end
|
55
|
+
expected_rules = <<-EOF
|
56
|
+
*mangle
|
57
|
+
:PREROUTING ACCEPT [9070264:2761485141]
|
58
|
+
:INPUT ACCEPT [5794:541194]
|
59
|
+
:FORWARD ACCEPT [9064470:2760943947]
|
60
|
+
:OUTPUT ACCEPT [4447:1027385]
|
61
|
+
:POSTROUTING ACCEPT [9068917:2761971332]
|
62
|
+
COMMIT
|
63
|
+
*nat
|
64
|
+
:PREROUTING ACCEPT [936831:58138468]
|
65
|
+
:INPUT ACCEPT [383149:28442596]
|
66
|
+
:OUTPUT ACCEPT [188115:19311882]
|
67
|
+
:POSTROUTING ACCEPT [88176135:5298607741]
|
68
|
+
:DOCKER - [0:0]
|
69
|
+
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 6379 -j DNAT --to-destination 172.17.0.2:6379
|
70
|
+
COMMIT
|
71
|
+
*filter
|
72
|
+
:INPUT ACCEPT [419:18560]
|
73
|
+
:FORWARD ACCEPT [5802508472:1613710597740]
|
74
|
+
:OUTPUT ACCEPT [2072879:485657573]
|
75
|
+
:FWR - [0:0]
|
76
|
+
COMMIT
|
77
|
+
EOF
|
78
|
+
expect { child.render == expected_rules }
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'allows filtering inherited chains' do
|
82
|
+
child = drumknott.bud do
|
83
|
+
inherit(:filter, :FWR) { |rule| !rule[:source] }
|
84
|
+
end
|
85
|
+
expected_rules = <<-EOF
|
86
|
+
*mangle
|
87
|
+
:PREROUTING ACCEPT [9070264:2761485141]
|
88
|
+
:INPUT ACCEPT [5794:541194]
|
89
|
+
:FORWARD ACCEPT [9064470:2760943947]
|
90
|
+
:OUTPUT ACCEPT [4447:1027385]
|
91
|
+
:POSTROUTING ACCEPT [9068917:2761971332]
|
92
|
+
COMMIT
|
93
|
+
*nat
|
94
|
+
:PREROUTING ACCEPT [936831:58138468]
|
95
|
+
:INPUT ACCEPT [383149:28442596]
|
96
|
+
:OUTPUT ACCEPT [188115:19311882]
|
97
|
+
:POSTROUTING ACCEPT [88176135:5298607741]
|
98
|
+
:DOCKER - [0:0]
|
99
|
+
COMMIT
|
100
|
+
*filter
|
101
|
+
:INPUT ACCEPT [419:18560]
|
102
|
+
:FORWARD ACCEPT [5802508472:1613710597740]
|
103
|
+
:OUTPUT ACCEPT [2072879:485657573]
|
104
|
+
:FWR - [0:0]
|
105
|
+
-A FWR -i lo -j ACCEPT
|
106
|
+
-A FWR -m state --state RELATED,ESTABLISHED -j ACCEPT
|
107
|
+
-A FWR -p icmp -j ACCEPT
|
108
|
+
-A FWR -i docker+ -j ACCEPT
|
109
|
+
-A FWR -p tcp -m tcp --dport 22 -j ACCEPT
|
110
|
+
-A FWR -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -j REJECT --reject-with icmp-port-unreachable
|
111
|
+
-A FWR -p udp -j REJECT --reject-with icmp-port-unreachable
|
112
|
+
COMMIT
|
113
|
+
EOF
|
114
|
+
expect { child.render == expected_rules }
|
115
|
+
expect { drumknott.render =~ /^-A FWR -s 1\.1\.1\.1/ }
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'copies original\'s chain with counters' do
|
119
|
+
child = ghq.bud do
|
120
|
+
inherit(:nat, :DOCKER)
|
121
|
+
table :filter do
|
122
|
+
chain :INPUT do
|
123
|
+
rule '-j FWR'
|
124
|
+
end
|
125
|
+
chain :FWR do
|
126
|
+
rule '-i lo -j ACCEPT'
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
expected_rules = <<-EOF
|
132
|
+
*nat
|
133
|
+
:PREROUTING ACCEPT [732601:44001989]
|
134
|
+
:INPUT ACCEPT [376018:22538408]
|
135
|
+
:OUTPUT ACCEPT [3131507:229597576]
|
136
|
+
:POSTROUTING ACCEPT [20476198:1943580383]
|
137
|
+
:DOCKER - [0:0]
|
138
|
+
[2:120] -A DOCKER ! -i docker0 -p tcp -m tcp --dport 2003 -j DNAT --to-destination 172.17.0.4:2003
|
139
|
+
[0:0] -A DOCKER ! -i docker0 -p tcp -m tcp --dport 2004 -j DNAT --to-destination 172.17.0.4:2004
|
140
|
+
[0:0] -A DOCKER ! -i docker0 -p tcp -m tcp --dport 49153 -j DNAT --to-destination 172.17.0.8:9000
|
141
|
+
[95:5580] -A DOCKER ! -i docker0 -p tcp -m tcp --dport 5000 -j DNAT --to-destination 172.17.0.5:5000
|
142
|
+
[0:0] -A DOCKER -d 127.0.0.1/32 ! -i docker0 -p tcp -m tcp --dport 49154 -j DNAT --to-destination 172.17.0.9:8080
|
143
|
+
[17011603:1693997647] -A DOCKER ! -i docker0 -p udp -m udp --dport 8125 -j DNAT --to-destination 172.17.0.10:8125
|
144
|
+
[0:0] -A DOCKER -d 127.0.0.1/32 ! -i docker0 -p tcp -m tcp --dport 49155 -j DNAT --to-destination 172.17.0.10:8126
|
145
|
+
COMMIT
|
146
|
+
*filter
|
147
|
+
:INPUT ACCEPT [1602:65593]
|
148
|
+
:FORWARD ACCEPT [79892700:14079015733]
|
149
|
+
:OUTPUT ACCEPT [173177551:46244981637]
|
150
|
+
:FWR - [0:0]
|
151
|
+
[162824485:36484450187] -A INPUT -j FWR
|
152
|
+
[104747465:21902005069] -A FWR -i lo -j ACCEPT
|
153
|
+
COMMIT
|
154
|
+
EOF
|
155
|
+
|
156
|
+
expect { child.render == expected_rules }
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
describe 'Ruleset#diff' do
|
161
|
+
it 'returns a Diffy::Diff from the original ruleset' do
|
162
|
+
child = Ruleset.from_file(fixture('only-docker.txt')).bud
|
163
|
+
|
164
|
+
expect { child.diff.to_s.each_line.grep(/^\S/).length == 7 }
|
165
|
+
|
166
|
+
child.dsl_eval do
|
167
|
+
inherit :filter, :FORWARD
|
168
|
+
end
|
169
|
+
|
170
|
+
expect { child.diff.to_s.each_line.grep(/^\S/).length == 4 }
|
171
|
+
|
172
|
+
child.dsl_eval do
|
173
|
+
table :nat do
|
174
|
+
chain :PREROUTING do
|
175
|
+
rule '-m addrtype --dst-type LOCAL -j DOCKER'
|
176
|
+
end
|
177
|
+
chain :OUTPUT do
|
178
|
+
rule '! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER'
|
179
|
+
end
|
180
|
+
chain :POSTROUTING do
|
181
|
+
rule '-s 172.17.0.0/16 ! -d 172.17.0.0/16 -j MASQUERADE'
|
182
|
+
rule '-s 10.0.3.0/24 ! -d 10.0.3.0/24 -j MASQUERADE'
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
expect { child.diff.to_s.empty? }
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
describe 'Ruleset#load_file' do
|
192
|
+
it 'Loads a ruleset from file' do
|
193
|
+
child = Ruleset.from_file(fixture('only-docker.txt')).bud
|
194
|
+
deny { child.diff.to_s.empty? }
|
195
|
+
child.load_file fixture('only_docker.rb')
|
196
|
+
expect { child.diff.to_s.empty? }
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|