puffy 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/CODEOWNERS +1 -0
- data/.github/workflows/ci.yml +23 -5
- data/.rubocop.yml +2 -0
- data/CHANGELOG.md +50 -0
- data/README.md +22 -13
- data/Rakefile +10 -0
- data/bin/puffy +2 -5
- data/lib/core_ext.rb +16 -4
- data/lib/puffy/cli.rb +1 -1
- data/lib/puffy/formatters/{netfilter.rb → iptables.rb} +7 -7
- data/lib/puffy/formatters/iptables4.rb +23 -0
- data/lib/puffy/formatters/iptables6.rb +23 -0
- data/lib/puffy/parser.tab.rb +406 -360
- data/lib/puffy/puppet.rb +4 -6
- data/lib/puffy/resolver.rb +32 -0
- data/lib/puffy/rule.rb +11 -2
- data/lib/puffy/rule_factory.rb +7 -5
- data/lib/puffy/version.rb +1 -1
- data/lib/puffy.rb +6 -3
- data/puffy.gemspec +2 -0
- metadata +23 -6
- data/lib/puffy/formatters/netfilter4.rb +0 -23
- data/lib/puffy/formatters/netfilter6.rb +0 -23
data/lib/puffy/puppet.rb
CHANGED
@@ -15,8 +15,8 @@ module Puffy
|
|
15
15
|
|
16
16
|
@formatters = [
|
17
17
|
Puffy::Formatters::Pf::Ruleset.new,
|
18
|
-
Puffy::Formatters::
|
19
|
-
Puffy::Formatters::
|
18
|
+
Puffy::Formatters::Iptables4::Ruleset.new,
|
19
|
+
Puffy::Formatters::Iptables6::Ruleset.new,
|
20
20
|
]
|
21
21
|
end
|
22
22
|
|
@@ -29,9 +29,7 @@ module Puffy
|
|
29
29
|
|
30
30
|
next unless fragment_changed?(fragment_name, fragment_content)
|
31
31
|
|
32
|
-
File.
|
33
|
-
f.write(fragment_content)
|
34
|
-
end
|
32
|
+
File.write(fragment_name, fragment_content)
|
35
33
|
end
|
36
34
|
end
|
37
35
|
|
@@ -67,7 +65,7 @@ module Puffy
|
|
67
65
|
def fragment_changed?(fragment_name, fragment_content)
|
68
66
|
return true unless File.exist?(fragment_name)
|
69
67
|
|
70
|
-
File.read(fragment_name).split("\n").
|
68
|
+
File.read(fragment_name).split("\n").grep_v(/^#/) != fragment_content.split("\n").grep_v(/^#/)
|
71
69
|
end
|
72
70
|
end
|
73
71
|
end
|
data/lib/puffy/resolver.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'open-uri'
|
3
4
|
require 'resolv'
|
4
5
|
require 'singleton'
|
5
6
|
|
@@ -29,8 +30,39 @@ module Puffy
|
|
29
30
|
end
|
30
31
|
end
|
31
32
|
|
33
|
+
# Resolve the SRV record for +service+ and return its target and port.
|
34
|
+
#
|
35
|
+
# @example
|
36
|
+
# Resolver.instance.resolv_srv('_http._tcp.deb.debian.org')
|
37
|
+
# #=> [{ host: 'debian.map.fastlydns.net.', port: 80 }]
|
38
|
+
#
|
39
|
+
# @param service [String] The service to resolve
|
40
|
+
# @return [Array<Hash>]
|
41
|
+
def resolv_srv(service)
|
42
|
+
proto = service.split('.')[1][1..-1].to_sym
|
43
|
+
@dns.getresources(service, Resolv::DNS::Resource::IN::SRV).collect { |r| { host: r.target.to_s, port: r.port, proto_hint: proto } }.sort
|
44
|
+
end
|
45
|
+
|
46
|
+
def resolv_apt_mirror(url)
|
47
|
+
res = []
|
48
|
+
http_url = url.sub(%r{^mirror(\+http)?://}, 'http://')
|
49
|
+
res << parse_url(http_url)
|
50
|
+
|
51
|
+
URI.parse(http_url).open do |document|
|
52
|
+
document.each_line do |line|
|
53
|
+
res << parse_url(line)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
res
|
57
|
+
end
|
58
|
+
|
32
59
|
private
|
33
60
|
|
61
|
+
def parse_url(url)
|
62
|
+
url =~ %r{^([^:]+)://([^/]+)}
|
63
|
+
{ host: Regexp.last_match(2), port: Regexp.last_match(1), proto_hint: :tcp }
|
64
|
+
end
|
65
|
+
|
34
66
|
def resolv_ipaddress(address, address_family)
|
35
67
|
filter_af(address, address_family)
|
36
68
|
end
|
data/lib/puffy/rule.rb
CHANGED
@@ -66,6 +66,8 @@ module Puffy
|
|
66
66
|
|
67
67
|
@af = detect_af unless af
|
68
68
|
|
69
|
+
self.proto ||= from_proto_hint || to_proto_hint
|
70
|
+
|
69
71
|
raise "unsupported action `#{options[:action]}'" unless valid_action?
|
70
72
|
raise 'if from_port or to_port is specified, the protocol must also be given' if port_without_protocol?
|
71
73
|
end
|
@@ -138,16 +140,22 @@ module Puffy
|
|
138
140
|
# Returns the source host of the Puffy::Rule.
|
139
141
|
# @!method from_port
|
140
142
|
# Returns the source port of the Puffy::Rule.
|
143
|
+
# @!method from_proto_hint
|
144
|
+
# Returns the proto hint of the Puffy::Rule.
|
141
145
|
# @!method to_host
|
142
146
|
# Returns the destination host of the Puffy::Rule.
|
143
147
|
# @!method to_port
|
144
148
|
# Returns the destination port of the Puffy::Rule.
|
149
|
+
# @!method to_proto_hint
|
150
|
+
# Returns the proto hint of the Puffy::Rule.
|
145
151
|
# @!method rdr_to_host
|
146
152
|
# Returns the redirect destination host of the Puffy::Rule.
|
147
153
|
# @!method rdr_to_port
|
148
154
|
# Returns the redirect destination port of the Puffy::Rule.
|
155
|
+
# @!method rdr_to_proto_hint
|
156
|
+
# Returns the proto hint of the Puffy::Rule (does not make sense).
|
149
157
|
%i[from to rdr_to].each do |destination|
|
150
|
-
%i[host port].each do |param|
|
158
|
+
%i[host port proto_hint].each do |param|
|
151
159
|
define_method("#{destination}_#{param}") do
|
152
160
|
res = public_send(destination)
|
153
161
|
res && res[param]
|
@@ -197,7 +205,8 @@ module Puffy
|
|
197
205
|
if res.nil? then nil
|
198
206
|
elsif res.ipv4? then :inet
|
199
207
|
elsif res.ipv6? then :inet6
|
200
|
-
else
|
208
|
+
else
|
209
|
+
raise 'Fail'
|
201
210
|
end
|
202
211
|
end.uniq.compact
|
203
212
|
end
|
data/lib/puffy/rule_factory.rb
CHANGED
@@ -34,7 +34,7 @@ module Puffy
|
|
34
34
|
def build(options = {})
|
35
35
|
return [] if options == {}
|
36
36
|
|
37
|
-
options = { action: nil, return: false, dir: nil, af: nil, proto: nil, on: nil, from: { host: nil, port: nil }, to: { host: nil, port: nil }, nat_to: nil, rdr_to: { host: nil, port: nil } }.merge(options)
|
37
|
+
options = { action: nil, return: false, dir: nil, af: nil, proto: nil, on: nil, from: [{ host: nil, port: nil }], to: [{ host: nil, port: nil }], nat_to: nil, rdr_to: [{ host: nil, port: nil }] }.merge(options)
|
38
38
|
|
39
39
|
options = resolv_hostnames_and_ports(options)
|
40
40
|
instanciate_rules(options)
|
@@ -44,8 +44,10 @@ module Puffy
|
|
44
44
|
|
45
45
|
def resolv_hostnames_and_ports(options)
|
46
46
|
%i[from to rdr_to].each do |endpoint|
|
47
|
-
options[endpoint]
|
48
|
-
|
47
|
+
options[endpoint].map do |ep|
|
48
|
+
ep[:host] = host_lookup(ep[:host])
|
49
|
+
ep[:port] = port_lookup(ep[:port])
|
50
|
+
end
|
49
51
|
end
|
50
52
|
options[:nat_to] = host_lookup(options[:nat_to])
|
51
53
|
options
|
@@ -74,8 +76,8 @@ module Puffy
|
|
74
76
|
end
|
75
77
|
end
|
76
78
|
|
77
|
-
def af_match_policy?(
|
78
|
-
@af.nil? ||
|
79
|
+
def af_match_policy?(address_family)
|
80
|
+
@af.nil? || address_family.nil? || address_family == @af
|
79
81
|
end
|
80
82
|
|
81
83
|
def host_lookup(host)
|
data/lib/puffy/version.rb
CHANGED
data/lib/puffy.rb
CHANGED
@@ -4,9 +4,9 @@ require 'core_ext'
|
|
4
4
|
|
5
5
|
require 'puffy/parser.tab'
|
6
6
|
require 'puffy/formatters/base'
|
7
|
-
require 'puffy/formatters/
|
8
|
-
require 'puffy/formatters/
|
9
|
-
require 'puffy/formatters/
|
7
|
+
require 'puffy/formatters/iptables'
|
8
|
+
require 'puffy/formatters/iptables4'
|
9
|
+
require 'puffy/formatters/iptables6'
|
10
10
|
require 'puffy/formatters/pf'
|
11
11
|
require 'puffy/puppet'
|
12
12
|
require 'puffy/resolver'
|
@@ -15,6 +15,7 @@ require 'puffy/rule_factory'
|
|
15
15
|
require 'puffy/version'
|
16
16
|
|
17
17
|
module Puffy
|
18
|
+
# Base class for application errors with a configuration file
|
18
19
|
class PuffyError < RuntimeError
|
19
20
|
def initialize(message, token)
|
20
21
|
super(message)
|
@@ -54,9 +55,11 @@ module Puffy
|
|
54
55
|
end
|
55
56
|
end
|
56
57
|
|
58
|
+
# Invalid configuration file
|
57
59
|
class ParseError < PuffyError
|
58
60
|
end
|
59
61
|
|
62
|
+
# Syntax error in configuration file
|
60
63
|
class SyntaxError < PuffyError
|
61
64
|
end
|
62
65
|
end
|
data/puffy.gemspec
CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.metadata['homepage_uri'] = spec.homepage
|
19
19
|
spec.metadata['source_code_uri'] = spec.homepage
|
20
20
|
spec.metadata['changelog_uri'] = spec.homepage
|
21
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
21
22
|
|
22
23
|
# Specify which files should be added to the gem when it is released.
|
23
24
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
@@ -36,6 +37,7 @@ Gem::Specification.new do |spec|
|
|
36
37
|
spec.add_development_dependency 'aruba'
|
37
38
|
spec.add_development_dependency 'bundler'
|
38
39
|
spec.add_development_dependency 'cucumber'
|
40
|
+
spec.add_development_dependency 'github_changelog_generator'
|
39
41
|
spec.add_development_dependency 'racc'
|
40
42
|
spec.add_development_dependency 'rake'
|
41
43
|
spec.add_development_dependency 'rspec'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puffy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Romain Tartière
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-12-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cri
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: github_changelog_generator
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: racc
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -200,11 +214,13 @@ executables:
|
|
200
214
|
extensions: []
|
201
215
|
extra_rdoc_files: []
|
202
216
|
files:
|
217
|
+
- ".github/CODEOWNERS"
|
203
218
|
- ".github/workflows/ci.yml"
|
204
219
|
- ".gitignore"
|
205
220
|
- ".rspec"
|
206
221
|
- ".rubocop.yml"
|
207
222
|
- ".simplecov"
|
223
|
+
- CHANGELOG.md
|
208
224
|
- Gemfile
|
209
225
|
- README.md
|
210
226
|
- Rakefile
|
@@ -213,9 +229,9 @@ files:
|
|
213
229
|
- lib/puffy.rb
|
214
230
|
- lib/puffy/cli.rb
|
215
231
|
- lib/puffy/formatters/base.rb
|
216
|
-
- lib/puffy/formatters/
|
217
|
-
- lib/puffy/formatters/
|
218
|
-
- lib/puffy/formatters/
|
232
|
+
- lib/puffy/formatters/iptables.rb
|
233
|
+
- lib/puffy/formatters/iptables4.rb
|
234
|
+
- lib/puffy/formatters/iptables6.rb
|
219
235
|
- lib/puffy/formatters/pf.rb
|
220
236
|
- lib/puffy/parser.tab.rb
|
221
237
|
- lib/puffy/puppet.rb
|
@@ -232,6 +248,7 @@ metadata:
|
|
232
248
|
homepage_uri: https://github.com/opus-codium/puffy
|
233
249
|
source_code_uri: https://github.com/opus-codium/puffy
|
234
250
|
changelog_uri: https://github.com/opus-codium/puffy
|
251
|
+
rubygems_mfa_required: 'true'
|
235
252
|
post_install_message:
|
236
253
|
rdoc_options: []
|
237
254
|
require_paths:
|
@@ -247,7 +264,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
247
264
|
- !ruby/object:Gem::Version
|
248
265
|
version: '0'
|
249
266
|
requirements: []
|
250
|
-
rubygems_version: 3.
|
267
|
+
rubygems_version: 3.3.23
|
251
268
|
signing_key:
|
252
269
|
specification_version: 4
|
253
270
|
summary: Network firewall rules made easy!
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Puffy
|
4
|
-
module Formatters
|
5
|
-
module Netfilter4 # :nodoc:
|
6
|
-
# IPv4 Netfilter implementation of a Puffy Ruleset formatter.
|
7
|
-
class Ruleset < Puffy::Formatters::Netfilter::Ruleset # :nodoc:
|
8
|
-
# Return an IPv4 Netfilter String representation of the provided +rules+ Puffy::Rule with the +policy+ policy.
|
9
|
-
def emit_ruleset(rules, policy = :block)
|
10
|
-
super(rules.select(&:ipv4?), policy)
|
11
|
-
end
|
12
|
-
|
13
|
-
def filename_fragment
|
14
|
-
['netfilter', 'rules.v4']
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
# IPv4 Netfilter implementation of a Puffy Rulet formatter.
|
19
|
-
class Rule < Puffy::Formatters::Netfilter::Rule # :nodoc:
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Puffy
|
4
|
-
module Formatters
|
5
|
-
module Netfilter6 # :nodoc:
|
6
|
-
# IPv6 Netfilter implementation of a Puffy Ruleset formatter.
|
7
|
-
class Ruleset < Puffy::Formatters::Netfilter::Ruleset # :nodoc:
|
8
|
-
# Return an IPv6 Netfilter String representation of the provided +rules+ Puffy::Rule with the +policy+ policy.
|
9
|
-
def emit_ruleset(rules, policy = :block)
|
10
|
-
super(rules.select(&:ipv6?), policy)
|
11
|
-
end
|
12
|
-
|
13
|
-
def filename_fragment
|
14
|
-
['netfilter', 'rules.v6']
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
# IPv6 Netfilter implementation of a Puffy Rule formatter.
|
19
|
-
class Rule < Puffy::Formatters::Netfilter::Rule # :nodoc:
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|