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,106 @@
1
+ module Iptablez
2
+ module Commands
3
+ # The namespace to describe the `iptables` `-X` argument to delete a chain.
4
+ # @author Kent 'picat' Gruber
5
+ module DeleteChain
6
+ # Move on Module
7
+ include MoveOn
8
+
9
+ NO_CHAIN_MATCH_ERROR = 'iptables: No chain/target/match by that name.'.freeze
10
+ CHAIN_NOT_EMPTY = 'iptables: Directory not empty.'.freeze
11
+
12
+ KNOWN_ERRORS = [NO_CHAIN_MATCH_ERROR, CHAIN_NOT_EMPTY].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)
17
+ if error == NO_CHAIN_MATCH_ERROR
18
+ raise ChainExistenceError, "#{chain} doesn't exist!"
19
+ elsif
20
+ raise ChainNotEmpty, "#{chain} is not empty! Will probably need to flush (-F) it to delete it!"
21
+ else
22
+ raise error
23
+ end
24
+ end
25
+
26
+ # Delete all of the user defined chains.
27
+ #
28
+ # @example Basic Usage
29
+ # Iptablez::Commands::DeleteChain.all
30
+ # # => {"dogs"=>true}
31
+ #
32
+ # @example Basic Usage with a Block
33
+ # Iptablez::Commands::DeleteChain.all do |name, result|
34
+ # puts "#{name} has been deleted." if result # true
35
+ # end
36
+ #
37
+ # @yield Each chain name and boolean if it has been successfully deleted.
38
+ # @return [Hash] Key value pairing of each user defined chain and boolean if it has been successfully deleted.
39
+ def self.all(error: false, continue: !error)
40
+ results = {}
41
+ chains(names: Iptablez::Chains.user_defined, continue: continue, fly_by: fly_by) do |name, result|
42
+ yield [name, result] if block_given?
43
+ results[name] = result
44
+ end
45
+ return false if results.empty?
46
+ results
47
+ end
48
+
49
+ # Delete a chain of a given +name+. This is the heart of this module.
50
+ # @param name [String] Single chain +name+.
51
+ # @param error [Boolean] Determine if operations should raise/halt other possible operations with errors.
52
+ # @param continue [Boolean] Determine if operations should continue despite errors.
53
+ #
54
+ # @example Basic Usage
55
+ # Iptablez::Commands::DeleteChain.chain(name: "dogs")
56
+ # # => false
57
+ # Iptablez::Commands::DeleteChain.chain(name: "cats")
58
+ # # => true
59
+ # @example Basic Usage with a Block
60
+ # Iptablez::Commands::DeleteChain.chain(name: "dogs") do |name, result|
61
+ # puts "#{name} deleted!" if result
62
+ # end
63
+ #
64
+ # @yield [String, Boolean] The +name+ of the chain and +result+ of the operation if a block if given.
65
+ # @return [Boolean] The result of the operation.
66
+ #
67
+ # @raise An error will be raised if the +error+ or +continue+ keywords are +true+ and the operation fails.
68
+ def self.chain(name:, error: false, continue: !error)
69
+ name = name.to_s unless name.is_a? String
70
+ _, e, s = Open3.capture3(Iptablez.bin_path, '-X', name.shellescape)
71
+ e.strip! # remove new line
72
+ if s.success?
73
+ yield [name, true] if block_given?
74
+ return true
75
+ elsif MoveOn.continue?(continue: continue, message: e, known_errors: KNOWN_ERRORS)
76
+ yield [name, false] if block_given?
77
+ return false
78
+ else
79
+ determine_error(chain: name, error: e)
80
+ end
81
+ end
82
+
83
+ # Delete each name is a given array of names.
84
+ # @param names [Array<String>] An array of chains to delete.
85
+ # @param error [Boolean] Determine if operations should raise/halt other possible operations with errors.
86
+ # @param continue [Boolean] Determine if operations should continue despite errors.
87
+ #
88
+ # @example Basic Usage
89
+ # Iptablez::Commands::DeleteChain.chain(names: ["dogs", "whales"])
90
+ # # => {"dogs"=>false, "whales"=>true}
91
+ #
92
+ # @yield [String, Boolean] The name of the chain and result of the operation if a block if given.
93
+ # @return [Hash] Key value pairing of each given chain and the result of the operation.
94
+ def self.chains(names:, error: false, continue: !error)
95
+ results = {}
96
+ names.each do |name|
97
+ results[name] = chain(name: name, continue: continue) do |name, result|
98
+ yield [name, result] if block_given?
99
+ end
100
+ end
101
+ results
102
+ end
103
+
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,72 @@
1
+ module Iptablez
2
+ module Commands
3
+ module FlushChain
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
+ # Flush all of the possible `iptables` chains.
11
+ # @example Basic Usage
12
+ # Iptablez::Commands::Flush.all
13
+ # # => {"INPUT"=>true, "FORWARD"=>true, "OUTPUT"=>true}
14
+ # @example Basic Usage with a Block
15
+ # Iptablez::Commands::Flush.all do |name, result|
16
+ # puts "#{name} flushed!" if result
17
+ # end
18
+ def self.all(names: Iptablez::Chains.all, error: false, continue: !error)
19
+ chains(names: names, continue: continue) do |name, result|
20
+ yield [name, result] if block_given?
21
+ end
22
+ end
23
+
24
+ # Flush the rules for a chain of a given `name`. This is the heart of this modules.
25
+ # @todo Document params.
26
+ # @example Basic Usage
27
+ # Iptablez::Commands::Flush.chain(name: "INPUT")
28
+ # # => true
29
+ # Iptablez::Commands::Flush.chain(name: "cats") # not a real chain
30
+ # # => false
31
+ # @example Basic Usage with a Block
32
+ # Iptablez::Commands::Flush.chain(name: "INPUT") do |name, result|
33
+ # puts "#{name} flushed" if result
34
+ # end
35
+ def self.chain(name:, error: false, continue: !error)
36
+ name = name.to_s unless name.is_a? String
37
+ _, e, s = Open3.capture3(Iptablez.bin_path, '-F', name.shellescape)
38
+ e.strip!
39
+ if s.success?
40
+ yield [name, true] if block_given?
41
+ return true
42
+ elsif MoveOn.continue?(continue: continue, message: e, known_errors: KNOWN_ERRORS)
43
+ yield [name, false] if block_given?
44
+ return false
45
+ else
46
+ determine_error(chain: name, error: e)
47
+ end
48
+ end
49
+
50
+ # Flush the rules for multiple chains of their given `names`.
51
+ # @todo Document params.
52
+ # @example Basic Usage
53
+ # Iptablez::Commands::Flush.chains(names: ["dogs", "cats"])
54
+ # # => {"dogs"=>true, "cats"=>false}
55
+ # @example Basic Usage with a Block
56
+ # Iptablez::Commands::Flush.chains(names: ["dogs", "cats"]) do |name, result|
57
+ # puts "#{name} flushed" if result
58
+ # end
59
+ def self.chains(names:, error: false, continue: !error)
60
+ results = {}
61
+ names.each do |name|
62
+ results[name] = chain(name: name, continue: continue) do |name, result|
63
+ yield [name, result] if block_given?
64
+ end
65
+ end
66
+ results
67
+ end
68
+
69
+
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,163 @@
1
+ module Iptablez
2
+ module Commands
3
+ # Kent, wtf is this shit?
4
+ # Don't worry about iiiiit bruuuhhhhhvvv.
5
+ # @author Kent 'picat' Gruber
6
+ module ArgumentHelpers
7
+
8
+ def self.wait(seconds: false)
9
+ if seconds # don't wait forever? :P
10
+ { wait: "-w #{seconds}" }
11
+ else
12
+ { wait: "-w" }
13
+ end
14
+ end
15
+
16
+ def self.counters(packets:, bytes:)
17
+ { counters: "-c #{packets} #{bytes}" }
18
+ end
19
+
20
+ def self.fragment
21
+ { fragment: "-f" }
22
+ end
23
+
24
+ def self.destination(dst:, ip: true, port: !ip)
25
+ unless port
26
+ { destination: "-d #{dst}" }
27
+ else
28
+ destination_port(dst: dst)
29
+ end
30
+ end
31
+
32
+ def self.destination_port(dst:)
33
+ { destination_port: "--dport #{dst}" }
34
+ end
35
+
36
+ def self.source(src:, ip: true, port: !ip)
37
+ unless port
38
+ { source: "-s #{src}" }
39
+ else
40
+ source_port(src: src)
41
+ end
42
+ end
43
+
44
+ def self.source_port(src:)
45
+ { source_port: "-sport #{src}" }
46
+ end
47
+
48
+ # @todo
49
+ #def self.ip_range(from:, to:)
50
+ # { ip_range: "-m iprange #{fromt}-#{to}" }
51
+ #end
52
+
53
+ def self.table(name: "filter")
54
+ { table: "-t #{name}" }
55
+ end
56
+
57
+ def self.jump(target:)
58
+ { jump: "-j #{target}" }
59
+ end
60
+
61
+ def self.goto(target:)
62
+ { goto: "-g #{target}" }
63
+ end
64
+
65
+ def self.interface(name:, out: false)
66
+ argument = if out
67
+ "-o"
68
+ else
69
+ "-i"
70
+ end
71
+ { interface: "#{argument} #{name}" }
72
+ end
73
+
74
+ def self.protocol(protocol:)
75
+ { protocol: "-p #{protocol}" }
76
+ end
77
+
78
+ # @example Basic Usage
79
+ # # note how jump: is compared to goto:
80
+ # args = {:goto=>"-g INPUT", :jump=>"INPUT"}
81
+ # # lets normalize that shit
82
+ # Iptablez::Commands::ArgumentHelpers.normalize_arguments(args)
83
+ # # => {:jump=>"-j INPUT", :goto=>"-g INPUT"}
84
+ def self.normalize_arguments(args)
85
+ results = {}
86
+ results[:jump] = normalize_jump(args[:jump])[:jump] if args[:jump]
87
+ results[:goto] = normalize_goto(args[:goto])[:goto] if args[:goto]
88
+ results[:protocol] = normalize_protocol(args[:protocol])[:protocol] if args[:protocol]
89
+ results[:interface]= normalize_interface(args[:interface])[:interface] if args[:interface]
90
+ results[:src] = normalize_source(args[:src])[:source] if args[:src]
91
+ results[:sport] = normalize_source(args[:sport], port: true)[:source_port] if args[:sport]
92
+ results[:dst] = normalize_destination(args[:dst])[:destination] if args[:dst]
93
+ results[:dport] = normalize_destination(args[:dport], port: true)[:destination_port] if args[:dport]
94
+ results
95
+ end
96
+
97
+ def self.normalize_jump(arg)
98
+ if arg["-j"] || arg["--jump"]
99
+ { jump: arg }
100
+ else
101
+ jump(target: arg)
102
+ end
103
+ end
104
+
105
+ def self.normalize_goto(arg)
106
+ if arg["-g"] || arg["--goto"]
107
+ { goto: arg }
108
+ else
109
+ goto(target: arg)
110
+ end
111
+ end
112
+
113
+ def self.normalize_protocol(arg)
114
+ if arg["-p"] # @todo Check || arg["--protocol"]
115
+ { protocol: arg }
116
+ else
117
+ goto(target: arg)
118
+ end
119
+ end
120
+
121
+ def self.normalize_interface(arg, out: false)
122
+ if arg["-i"] || arg["-o"] # @todo
123
+ { interface: arg }
124
+ else
125
+ interface(name: arg, out: out)
126
+ end
127
+ end
128
+
129
+ def self.normalize_table(arg)
130
+ if arg["-t"] || arg["--table"] # @todo
131
+ { table: arg }
132
+ else
133
+ table(name: arg)
134
+ end
135
+ end
136
+
137
+ def self.normalize_destination(arg, port: false)
138
+ if arg["-d"] || arg["--dport"] # @todo
139
+ if port
140
+ { destination_port: arg }
141
+ else
142
+ { destination: arg }
143
+ end
144
+ else
145
+ destination(dst: arg, port: port)
146
+ end
147
+ end
148
+
149
+ def self.normalize_source(arg, port: false)
150
+ if arg["-s"] || arg["--sport"] # @todo
151
+ if port
152
+ { source_port: arg }
153
+ else
154
+ { source: arg }
155
+ end
156
+ else
157
+ source(src: arg, port: port)
158
+ end
159
+ end
160
+
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,11 @@
1
+ module Iptablez
2
+ module Commands
3
+ class ChainExistenceError < ArgumentError; end
4
+
5
+ class ChainNotEmpty < StandardError ; end
6
+
7
+ class InvalidRuleIndexError < StandardError; end
8
+
9
+ class ChainAlreadyExistsError < ArgumentError; end
10
+ end
11
+ end
@@ -0,0 +1,14 @@
1
+ module Iptablez
2
+ module Commands
3
+ # @todo Document this module. Kind'a important.
4
+ module MoveOn
5
+ # @api private
6
+ # Determine if the method should should move on with its life when things go wrong.
7
+ def self.continue?(continue:, message:, known_errors:, force: false)
8
+ return true if force
9
+ return true if continue && known_errors.include?(message)
10
+ false
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,80 @@
1
+ module Iptablez
2
+ module Commands
3
+ # @todo Add inline document to this.
4
+ module Interface
5
+
6
+ def self.delete_chain(name: false, all: false)
7
+ if name
8
+ DeleteChain.chain(name: name)
9
+ elsif all
10
+ DeleteChain.all
11
+ else
12
+ raise "No chain name/all specified."
13
+ end
14
+ end
15
+
16
+ def self.flush(chain: false, all: true)
17
+ if chain
18
+ Flush.chain(name: chain)
19
+ elsif all
20
+ Flush.all
21
+ else
22
+ raise "No chain/all specified."
23
+ end
24
+ end
25
+
26
+ def self.list(chain: false, all: true, number: false)
27
+ if chain && ! number
28
+ List.chain(name: chain)
29
+ elsif number && chain
30
+ List.number(chain: chain, number: number)
31
+ elsif all
32
+ List.all
33
+ else
34
+ raise "No chain/number/all specified."
35
+ end
36
+ end
37
+
38
+ def self.new_chain(name:)
39
+ NewChain.chain(name: name)
40
+ end
41
+
42
+ def self.policy(target:, chain: false, all: true)
43
+ if chain && target
44
+ Policy.chain(name: chain, target: target)
45
+ elsif all && target
46
+ Policy.all(target: target)
47
+ else
48
+ raise "No chain/target/all specified."
49
+ end
50
+ end
51
+
52
+ def self.rename_chain(from:, to:)
53
+ if from && to
54
+ RenameChain.chain(from: from, to: to)
55
+ else
56
+ raise "No from/to specified."
57
+ end
58
+ end
59
+
60
+ def self.version(full: false)
61
+ if full
62
+ Version.full
63
+ else
64
+ Version.number
65
+ end
66
+ end
67
+
68
+ def self.zero(all: true, chain: false)
69
+ if chain
70
+ Zero.chain(name: chain)
71
+ elsif all
72
+ Zero.all
73
+ else
74
+ raise "No all/chain specified."
75
+ end
76
+ end
77
+
78
+ end
79
+ end
80
+ end