iptablez 1.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,210 @@
1
+ module Iptablez
2
+ module Commands
3
+ module List
4
+ # Move on Module
5
+ include MoveOn
6
+
7
+ UNKOWN_OPTION = 'unknown option'.freeze
8
+ NO_CHAIN_MATCH_ERROR = 'iptables: No chain/target/match by that name.'.freeze
9
+ PERMISSION_DENIED = 'Permission denied (you must be root)'.freeze
10
+ INVALID_RULE_NUMBER = 'Invalid rule number'.freeze
11
+
12
+ KNOWN_ERRORS = [NO_CHAIN_MATCH_ERROR, PERMISSION_DENIED, INVALID_RULE_NUMBER, UNKOWN_OPTION].freeze
13
+
14
+ # @api private
15
+ # Determine a given error. Optionally a chain can be used to provide better context.
16
+ private_class_method def self.determine_error(error:, chain: false, number: false)
17
+ if error == NO_CHAIN_MATCH_ERROR
18
+ raise ChainExistenceError, "#{chain} doesn't exist!"
19
+ elsif error == INVALID_RULE_NUMBER
20
+ raise InvalidRuleIndexError, "#{chain} invalid number #{number}!"
21
+ else
22
+ raise error
23
+ end
24
+ end
25
+
26
+ # List all of the `iptables` rules. Note: this will not include policies.
27
+ # @todo Document params.
28
+ # @example Basic Usage
29
+ # Iptablez::Commands::List.all
30
+ # # => []
31
+ # Iptablez::Commands::List.all.empty? # if no rules
32
+ # # => true
33
+ # @example Basic Usage with a Block
34
+ # Iptablez::Commands::List.all do |rule|
35
+ # puts rule
36
+ # end
37
+ # @yield Each result if a block is given.
38
+ # @return [Hash] key value pairing of each chain and the result of the check.
39
+ def self.all(error: false, continue: !error)
40
+ o, e, s = Open3.capture3(Iptablez.bin_path, '-L')
41
+ if e["you must be root"]
42
+ e = PERMISSION_DENIED
43
+ else
44
+ e.strip!
45
+ end
46
+ results = []
47
+ if s.success?
48
+ o.split("\n").map(&:strip).each do |line|
49
+ next if line.split[0] == "Chain" || line.split[0] == "target" || line.empty?
50
+ yield line if block_given?
51
+ results << line
52
+ end
53
+ results
54
+ elsif MoveOn.continue?(continue: continue, message: e, known_errors: KNOWN_ERRORS)
55
+ return results
56
+ else
57
+ determine_error(chain: name, error: e)
58
+ end
59
+ end
60
+
61
+ # List the `iptables` rules for a chain of a given `name`.
62
+ # @todo Document params.
63
+ # @example Basic Usage
64
+ # Iptablez::Commands::List.defaults
65
+ # # => {"INPUT"=>"ACCEPT", "FORWARD"=>"ACCEPT", "OUTPUT"=>"ACCEPT"}
66
+ # @example Basic Usage with a Block
67
+ # Iptablez::Commands::List.defaults do |name, target|
68
+ # puts "#{name}: #{target}"
69
+ # end
70
+ def self.defaults(names: Iptablez::Chains.defaults, error: false, continue: !error)
71
+ results = {}
72
+ names.each do |name|
73
+ result = chain(name: name, policy: true, continue: true)
74
+ result = result.map(&:split).map(&:last)[0] if result
75
+ yield [name, result] if block_given?
76
+ results[name] = result
77
+ end
78
+ results
79
+ end
80
+
81
+ # List the full `iptables` output (no filtering from STDOUT) for a `chain` of a given name, or
82
+ # all chains if no chain `name` is given.
83
+ # @todo Document params.
84
+ # @example Basic Usage
85
+ # Iptablez::Commands::List.full
86
+ # Iptablez::Commands::List.full(chain: "INPUT")
87
+ # @example Basic Usage with a Block
88
+ # Iptablez::Commands::List.full { |l| puts l }
89
+ # Iptablez::Commands::List.full(chain: "FORWARD") do |line|
90
+ # puts line
91
+ # end
92
+ # @yield Each result if a block is given.
93
+ # @return [Array] Each line as the result.
94
+ def self.full(chain: false, error: false, continue: !error)
95
+ if chain
96
+ o, e, s = Open3.capture3(Iptablez.bin_path, '-L', chain)
97
+ else
98
+ o, e, s = Open3.capture3(Iptablez.bin_path, '-L')
99
+ end
100
+ e.strip!
101
+ if s.success?
102
+ return o.split("\n").map(&:strip).each do |line|
103
+ yield line if block_given?
104
+ end
105
+ elsif MoveOn.continue?(continue: continue, message: e, known_errors: KNOWN_ERRORS)
106
+ return false
107
+ else
108
+ determine_error(chain: name, error: e)
109
+ end
110
+ end
111
+
112
+ # List a rule for a `chain` of a given name and `number`.
113
+ # @example Basic Usage
114
+ # Iptablez::Commands::List.number(chain: "INPUT", number: 1)
115
+ # # => false
116
+ # Iptablez::Commands::List.number(chain: "FORWARD", number: 1)
117
+ # # => String containing rule number 1 from the FOWARD chain.
118
+ # @example Basic Usage with a Block
119
+ # Iptablez::Commands::List.number(chain: "INPUT", number: 1) do |chain, num, result|
120
+ # puts "Rule #{num} in #{chain} is #{result}" if result
121
+ # end
122
+ def self.number(chain:, number:, error: false, continue: !error)
123
+ if number.is_a? Integer
124
+ if number <= 0 && error
125
+ raise ArgumentError, "Invalid rule number #{number}!"
126
+ else
127
+ number = number.to_s
128
+ end
129
+ end
130
+ o, e, s = Open3.capture3(Iptablez.bin_path, '-L', chain, number.to_s)
131
+ e.strip!
132
+ o.strip!
133
+ o = false if o.empty?
134
+ e = INVALID_RULE_NUMBER if e["Invalid rule number"]
135
+ e = UNKOWN_OPTION if e[": unknown option "]
136
+ if s.success?
137
+ yield [chain, number, o] if block_given?
138
+ return o
139
+ elsif MoveOn.continue?(continue: continue, message: e, known_errors: KNOWN_ERRORS)
140
+ return false
141
+ else
142
+ determine_error(chain: name, error: e, number: number)
143
+ end
144
+ end
145
+
146
+ # Determine if there is a rule for a given `chain` name with a given `number`.
147
+ # @example Basic Usage
148
+ # Iptablez::Commands::List.number?(chain: "INPUT", number: 1)
149
+ # # => false
150
+ # Iptablez::Commands::List.number?(chain: "FORWARD", number: 1)
151
+ # # => true
152
+ def self.number?(chain:, number:, error: false, continue: !error)
153
+ if number(chain: chain, number: number, continue: continue)
154
+ true
155
+ else
156
+ false
157
+ end
158
+ end
159
+
160
+ # Determine if a given `number` could even be a possible number. Note: this will not
161
+ # check `iptables` for validation.
162
+ # @example Basic Usage
163
+ # Iptablez::Commands::List.possible_valid_number?(number: 2)
164
+ # # => true
165
+ # Iptablez::Commands::List.possible_valid_number?(number: 0)
166
+ # # => false
167
+ def self.possible_valid_number?(number:)
168
+ number = number.to_i if number.is_a? String
169
+ if number >= 1
170
+ true
171
+ else
172
+ false
173
+ end
174
+ end
175
+
176
+ # List the `iptables` rules for a chain of a given `name`. Optionally, you
177
+ # may specify to include `policy` information which can be helpful.
178
+ # @example Basic Usage
179
+ # Iptablez::Commands::List.chain(name: "INPUT")
180
+ # # => []
181
+ # Iptablez::Commands::List.chain(name: "INPUT", policy: true)
182
+ # # => ["-P INPUT ACCEPT"]
183
+ # @example Basic Usage with a Block
184
+ # Iptablez::Commands::List.chain(name: "INPUT", policy: true) do |rule|
185
+ # puts rule
186
+ # end
187
+ def self.chain(name:, policy: false, error: false, continue: !error)
188
+ if policy
189
+ o, e, s = Open3.capture3(Iptablez.bin_path, '-S', name)
190
+ else
191
+ o, e, s = Open3.capture3(Iptablez.bin_path, '-L', name)
192
+ end
193
+ e.strip!
194
+ if s.success?
195
+ results = o.split("\n").map(&:strip).delete_if do |line|
196
+ line if line.split[0] == "Chain" || line.split[0] == "target"
197
+ end
198
+ results.each do |line|
199
+ yield line if block_given?
200
+ end
201
+ results
202
+ elsif MoveOn.continue?(continue: continue, message: e, known_errors: KNOWN_ERRORS)
203
+ return false
204
+ else
205
+ determine_error(chain: name, error: e)
206
+ end
207
+ end
208
+ end
209
+ end
210
+ end
@@ -0,0 +1,71 @@
1
+ module Iptablez
2
+ module Commands
3
+ module NewChain
4
+ # Move on Module
5
+ include MoveOn
6
+
7
+ CHAIN_ALREADY_EXITS_ERROR = 'iptables: Chain already exists.'
8
+ KNOWN_ERRORS = [CHAIN_ALREADY_EXITS_ERROR]
9
+
10
+ # @api private
11
+ # Determine a given error. Optionally a chain can be used to provide better context.
12
+ private_class_method def self.determine_error(error:, chain: false)
13
+ error.strip!
14
+ if error == CHAIN_ALREADY_EXITS_ERROR
15
+ raise ChainAlreadyExistsError, "#{chain} already exist!"
16
+ else
17
+ raise error
18
+ end
19
+ end
20
+
21
+ # Create a new chain of a given +name+, unless is already exists. This is the heart of the module.
22
+ # @param name [String] Single chain +name+.
23
+ # @param error [Boolean] Determine if operations should raise/halt other possible operations with errors.
24
+ # @param continue [Boolean] Determine if operations should continue despite errors.
25
+ #
26
+ # @example Basic Usage
27
+ # Iptablez::Commands::NewChain.chain(name: "dogs")
28
+ # # => true
29
+ # Iptablez::Commands::NewChain.chain(name: "dogs")
30
+ # # => false
31
+ # @yield [String, Boolean] The +name+ of the chain and +result+ of the operation if a block if given.
32
+ # @return [String, Boolean] Key value pairing of the given chain +name+ and the +result+ of the operation.
33
+ def self.chain(name:, error: false, continue: !error)
34
+ name = name.to_s unless name.is_a? String
35
+ _, e, s = Open3.capture3(Iptablez.bin_path, '-N', name.shellescape)
36
+ e.strip! # remove new line
37
+ if s.success?
38
+ yield [name, true] if block_given?
39
+ return true
40
+ elsif MoveOn.continue?(continue: continue, message: e, known_errors: KNOWN_ERRORS)
41
+ yield [name, false] if block_given?
42
+ return false
43
+ else
44
+ determine_error(chain: name, error: e)
45
+ end
46
+ end
47
+
48
+ # Create each +name+ from a given array of +names+ unless the chain already exists.
49
+ # @param names [Array<String>] An array of chains to delete.
50
+ # @param error [Boolean] Determine if operations should raise/halt other possible operations with errors.
51
+ # @param continue [Boolean] Determine if operations should continue despite errors.
52
+ #
53
+ # @example Basic Usage
54
+ # Iptablez::Commands::DeleteChain.chain(names: ["dogs", "whales"])
55
+ # # => {"dogs"=>false, "whales"=>true}
56
+ #
57
+ # @yield [String, Boolean] The +name+ of the chain and +result+ of the operation if a block if given.
58
+ # @return [Hash] Key value pairing of each given chain +name+ and the +result+ of the operation.
59
+ def self.chains(names:, error: false, continue: !error)
60
+ results = {}
61
+ names.each do |name|
62
+ chain(name: name, continue: continue) do |name, result|
63
+ yield [name, result] if block_given?
64
+ results[name] = result
65
+ end
66
+ end
67
+ results
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,65 @@
1
+ module Iptablez
2
+ module Commands
3
+ module Policy
4
+ # Move on Module
5
+ include MoveOn
6
+
7
+ NO_CHAIN_MATCH_ERROR = 'iptables: No chain/target/match by that name.'.freeze
8
+ KNOWN_ERRORS = [NO_CHAIN_MATCH_ERROR].freeze
9
+
10
+ # @api private
11
+ # Determine a given error. Optionally a chain can be used to provide better context.
12
+ private_class_method def self.determine_error(error:, chain: false)
13
+ if error == NO_CHAIN_MATCH_ERROR
14
+ raise ChainExistenceError, "#{chain} doesn't exist!"
15
+ else
16
+ raise error
17
+ end
18
+ end
19
+
20
+ def self.all(target:, error: false, continue: !error)
21
+ if target
22
+ chains(names: Iptablez::Chains.defaults, target: target, continue: continue) do |result|
23
+ yield result if block_given?
24
+ end
25
+ else
26
+ Iptables::Chains.policies do |result|
27
+ yield result
28
+ end
29
+ end
30
+ end
31
+
32
+ def self.defaults(target:, error: false, continue: !error)
33
+ chains(names: Iptablez::Chains.defaults, target: target, continue: continue) do |result|
34
+ yield result if block_given?
35
+ end
36
+ end
37
+
38
+ def self.chain(name:, target:, error: false, continue: !error)
39
+ _, e, s = Open3.capture3(Iptablez.bin_path, '-P', name, target)
40
+ e.strip!
41
+ if s.success?
42
+ yield [name, target, true] if block_given?
43
+ return true
44
+ elsif MoveOn.continue?(continue: continue, message: e, known_errors: KNOWN_ERRORS)
45
+ yield [name, target, false] if block_given?
46
+ return false
47
+ else
48
+ determine_error(chain: name, error: e)
49
+ end
50
+ end
51
+
52
+ def self.chains(names:, target:, error: false, continue: !error)
53
+ results = {}
54
+ names.each do |name|
55
+ results[name] = {}
56
+ results[name][target] = chain(name: name, target: target, continue: continue) do |result|
57
+ yield result if block_given?
58
+ end
59
+ end
60
+ results
61
+ end
62
+
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,65 @@
1
+ module Iptablez
2
+ module Commands
3
+ module RenameChain
4
+ # Move on Module
5
+ include MoveOn
6
+
7
+
8
+ NO_CHAIN_MATCH_ERROR = 'iptables: No chain/target/match by that name.'.freeze
9
+ CHAIN_ALREADY_EXISTS = 'iptables: File exists.'.freeze
10
+ KNOWN_ERRORS = [NO_CHAIN_MATCH_ERROR, CHAIN_ALREADY_EXISTS].freeze
11
+
12
+ # @api private
13
+ # Determine a given error. Optionally a chain can be used to provide better context.
14
+ private_class_method def self.determine_error(error:, chain: false)
15
+ if error == NO_CHAIN_MATCH_ERROR
16
+ raise ChainExistenceError, "#{chain} doesn't exist!"
17
+ elsif error == CHAIN_ALREADY_EXISTS
18
+ raise ChainExistenceError, "#{chain} already exists!"
19
+ else
20
+ raise error
21
+ end
22
+ end
23
+
24
+ # Rename a chain +from+ a given name +to+ a new name. This is the heart of this module.
25
+ # @param from [String] Single chain name to change +from+.
26
+ # @param to [String] Single chain name to change +to+.
27
+ #
28
+ # @example Basic Usage
29
+ # Iptablez::Commands::RenameChain.chain(from: "dogs", to: "cats")
30
+ # # => true
31
+ # Iptablez::Commands::RenameChain.chain(from: "dogs", to: "birds")
32
+ # # => false
33
+ #
34
+ # @yield [String, String]
35
+ # @return [Boolean]
36
+ def self.chain(from:, to:, error: false, continue: !error)
37
+ to = to.to_s unless to.is_a? String
38
+ from = from.to_s unless from.is_a? String
39
+ _, e, s = Open3.capture3(Iptablez.bin_path, '-E', from.shellescape, to.shellescape)
40
+ e.strip!
41
+ if s.success?
42
+ yield [from, to, true] if block_given?
43
+ return true
44
+ elsif MoveOn.continue?(continue: continue, message: e, known_errors: KNOWN_ERRORS)
45
+ yield [from, to, false] if block_given?
46
+ return false
47
+ else
48
+ determine_error(chain: name, error: e)
49
+ end
50
+ end
51
+
52
+ def self.chains(pairs:, error: false, continue: !error)
53
+ results = {}
54
+ pairs.each do |from, to|
55
+ results[from] = {}
56
+ results[from][to] = chain(from: from, to: to, continue: continue) do |from, to, result|
57
+ yield [from, to, result] if block_given?
58
+ end
59
+ end
60
+ results
61
+ end
62
+
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,18 @@
1
+ module Iptablez
2
+ module Commands
3
+ # @todo
4
+ module Version
5
+ def self.number
6
+ o, e, s = Open3.capture3(Iptablez.bin_path, '--version')
7
+ return o.strip.split[1].gsub('v','') if s.success?
8
+ raise e
9
+ end
10
+
11
+ def self.full
12
+ o, e, s = Open3.capture3(Iptablez.bin_path, '--version')
13
+ return o.strip if s.success?
14
+ raise e
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ module Iptablez
2
+ module Commands
3
+ # @todo
4
+ module Zero
5
+ def self.all
6
+ o, e, s = Open3.capture3(Iptablez.bin_path, '-Z')
7
+ return true if s.success?
8
+ raise e
9
+ end
10
+
11
+ def self.chain(name:)
12
+ o, e, s = Open3.capture3(Iptablez.bin_path, '-Z', name)
13
+ return true if s.success?
14
+ raise e
15
+ end
16
+ end
17
+ end
18
+ end