iptablez 1.0.0.pre

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.
@@ -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