puffy 0.3.1 → 1.1.0.pre.rc1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ccc93913a571a25b75f1984f53315be9df0001f27fd7d1062c274a8ae398a890
4
- data.tar.gz: e39938f8393291ccdf37f4c9817abb1dd40c8816a67cadf9c5aea43d57b3969c
3
+ metadata.gz: 212bbb0b9badf3e5595984f60e85f1739c907434fa65b6498279803111499fd7
4
+ data.tar.gz: 148f4d57788cc7db0fdee92a6758be60c698a8d59f76e89804875f5424ab52e2
5
5
  SHA512:
6
- metadata.gz: c701450c7f9fcd9417cde14b41e25381beeec5ef835931e8bfdc30ee10a539b951503b907866d7176064218bfa4120f1ddfc594a4ab461ccf4034221940fa2b4
7
- data.tar.gz: 91c204a40f678eaf37ada1ed9f48a4a7ca08e012296df8f8cb2ed92d533a0044b5282ffe19d3ba9abdbb604a8bd12c2e425feca6a894215ec5d458f6b6d4d8a0
6
+ metadata.gz: 96a3238a90ebb5625ad18279b9b72ec1f122cde54463a6377238091a5e4a5ac8ebb6488fd0de0d176b2b73589e41991eecb53c824c26d5d62f8e7f5c17300d07
7
+ data.tar.gz: 97a3e613aa975b7e0828bc467f5d485b81eb24eef6771cc90927f3fa6dfdedfa3a142de61ac22c3952c8a042b41788b18270100df0639102de2fd4441a157c36
@@ -0,0 +1,18 @@
1
+ # To get started with Dependabot version updates, you'll need to specify which
2
+ # package ecosystems to update and where the package manifests are located.
3
+ # Please see the documentation for all configuration options:
4
+ # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5
+
6
+ version: 2
7
+ updates:
8
+ # Open PR for gem updates
9
+ - package-ecosystem: "bundler" # See documentation for possible values
10
+ directory: "/" # Location of package manifests
11
+ schedule:
12
+ interval: "daily"
13
+
14
+ # Open PR for GitHub Actions updates
15
+ - package-ecosystem: "github-actions"
16
+ directory: "/"
17
+ schedule:
18
+ interval: "daily"
@@ -14,7 +14,7 @@ jobs:
14
14
  rubocop:
15
15
  runs-on: ubuntu-latest
16
16
  steps:
17
- - uses: actions/checkout@v2
17
+ - uses: actions/checkout@v6
18
18
  - name: Setup ruby
19
19
  uses: ruby/setup-ruby@v1
20
20
  with:
@@ -33,9 +33,10 @@ jobs:
33
33
  - "3.0"
34
34
  - "3.1"
35
35
  - "3.2"
36
+ - "3.3"
36
37
  name: Ruby ${{ matrix.ruby }}
37
38
  steps:
38
- - uses: actions/checkout@v2
39
+ - uses: actions/checkout@v6
39
40
  - name: Setup ruby
40
41
  uses: ruby/setup-ruby@v1
41
42
  with:
@@ -44,12 +45,4 @@ jobs:
44
45
  - name: Generate the parser
45
46
  run: bundle exec rake gen_parser
46
47
  - name: Run tests without uploading code coverage
47
- if: ${{ matrix.ruby != '3.0' }}
48
48
  run: bundle exec rake
49
- - name: Run tests and upload coverage to Code Climate
50
- if: ${{ matrix.ruby == '3.0' }}
51
- uses: paambaati/codeclimate-action@v3.0.0
52
- env:
53
- CC_TEST_REPORTER_ID: ${{ secrets.CODECLIMATE_TOKEN }}
54
- with:
55
- coverageCommand: bundle exec rake
data/.rubocop.yml CHANGED
@@ -7,6 +7,10 @@ AllCops:
7
7
  - tmp/**/*.rb
8
8
  - vendor/bundle/**/*
9
9
 
10
+ plugins:
11
+ - rubocop-rake
12
+ - rubocop-rspec
13
+
10
14
  Layout/HashAlignment:
11
15
  EnforcedColonStyle: table
12
16
  EnforcedHashRocketStyle: table
@@ -26,6 +30,16 @@ Metrics/ModuleLength:
26
30
  Exclude:
27
31
  - spec/**/*.rb
28
32
 
33
+ RSpec/ExampleLength:
34
+ Max: 50
35
+
36
+ RSpec/MultipleExpectations:
37
+ Max: 10
38
+
39
+ RSpec/SpecFilePathFormat:
40
+ Exclude:
41
+ - spec/core_ext_spec.rb
42
+
29
43
  Style/Documentation:
30
44
  Exclude:
31
45
  - features/support/env.rb
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## [v1.0.0](https://github.com/opus-codium/puffy/tree/v1.0.0) (2024-04-09)
4
+
5
+ [Full Changelog](https://github.com/opus-codium/puffy/compare/v0.3.1...v1.0.0)
6
+
7
+ **Implemented enhancements:**
8
+
9
+ - Setup dependabot [\#36](https://github.com/opus-codium/puffy/pull/36) ([smortex](https://github.com/smortex))
10
+ - Add support for Ruby 3.3 [\#33](https://github.com/opus-codium/puffy/pull/33) ([smortex](https://github.com/smortex))
11
+
3
12
  ## [v0.3.1](https://github.com/opus-codium/puffy/tree/v0.3.1) (2023-11-22)
4
13
 
5
14
  [Full Changelog](https://github.com/opus-codium/puffy/compare/v0.3.0...v0.3.1)
data/README.md CHANGED
@@ -25,6 +25,13 @@ Rules must appear in either a *node* or *service* definition, *services* being
25
25
  reusable blocks of related rules:
26
26
 
27
27
  ~~~
28
+ policy block in all
29
+ policy block out log all
30
+
31
+ service dns do
32
+ pass proto {tcp udp} to port domain
33
+ end
34
+
28
35
  service ntp do
29
36
  pass proto udp to port ntp
30
37
  end
@@ -42,6 +49,7 @@ service www do
42
49
  end
43
50
 
44
51
  service base do
52
+ client dns
45
53
  client ntp
46
54
  server ssh
47
55
  end
data/Rakefile CHANGED
@@ -14,7 +14,7 @@ Cucumber::Rake::Task.new(:features)
14
14
  GitHubChangelogGenerator::RakeTask.new :changelog do |config|
15
15
  config.user = 'opus-codium'
16
16
  config.project = 'puffy'
17
- config.exclude_labels = ['skip-changelog']
17
+ config.exclude_labels = %w[dependencies skip-changelog]
18
18
  config.future_release = "v#{Puffy::VERSION}"
19
19
  end
20
20
 
@@ -22,11 +22,15 @@ task test: %i[spec features]
22
22
 
23
23
  task default: :test
24
24
 
25
+ # rubocop:disable Rake/Desc
26
+ task feature: :gen_parser
25
27
  task build: :gen_parser
28
+ task spec: :gen_parser
29
+ # rubocop:enable Rake/Desc
26
30
 
27
31
  desc 'Generate the puffy language parser'
28
32
  task gen_parser: 'lib/puffy/parser.tab.rb'
29
33
 
30
34
  file 'lib/puffy/parser.tab.rb' => 'lib/puffy/parser.y' do
31
- `racc -S lib/puffy/parser.y`
35
+ `racc --embedded --frozen --output-status lib/puffy/parser.y`
32
36
  end
data/lib/core_ext.rb CHANGED
@@ -59,15 +59,13 @@ end
59
59
 
60
60
  class Array # :nodoc:
61
61
  def deep_dup
62
- array = []
63
- each do |value|
64
- array << if value.respond_to?(:deep_dup)
65
- value.deep_dup
66
- else
67
- value.dup
68
- end
62
+ map do |value|
63
+ if value.respond_to?(:deep_dup)
64
+ value.deep_dup
65
+ else
66
+ value.dup
67
+ end
69
68
  end
70
- array
71
69
  end
72
70
  end
73
71
 
data/lib/puffy/cli.rb CHANGED
@@ -49,10 +49,10 @@ module Puffy
49
49
  run do |opts, args|
50
50
  parser = cli.load_network(args[:network])
51
51
  rules = parser.ruleset_for(args[:hostname])
52
- policy = parser.policy_for(args[:hostname])
52
+ policies = parser.policies_for(args[:hostname])
53
53
 
54
54
  formatter = Object.const_get("Puffy::Formatters::#{opts[:formatter]}::Ruleset").new
55
- puts formatter.emit_ruleset(rules, policy)
55
+ puts formatter.emit_ruleset(rules, policies)
56
56
  end
57
57
  end
58
58
 
@@ -34,12 +34,12 @@ module Puffy
34
34
  ["# Generated by puffy v#{Puffy::VERSION} on #{Time.now.strftime('%c')}"]
35
35
  end
36
36
 
37
- # Returns a String representation of the provided +rules+ Array of Puffy::Rule with the +policy+ policy.
37
+ # Returns a String representation of the provided +rules+ Array of Puffy::Rule with the +policies+ policies.
38
38
  #
39
39
  # @param rules [Array<Puffy::Rule>] array of Puffy::Rule.
40
- # @param _policy [Symbol] ruleset policy.
40
+ # @param _policies [Symbol] ruleset policies.
41
41
  # @return [String]
42
- def emit_ruleset(rules, _policy = nil)
42
+ def emit_ruleset(rules, _policies = nil)
43
43
  rules.collect { |rule| @rule_formatter.emit_rule(rule) }.join("\n")
44
44
  end
45
45
 
@@ -27,13 +27,13 @@ module Puffy
27
27
  }
28
28
  end
29
29
 
30
- # Returns a Iptables String representation of the provided +rules+ Array of Puffy::Rule with the +policy+ policy.
31
- def emit_ruleset(rules, policy = :block)
30
+ # Returns a Iptables String representation of the provided +rules+ Array of Puffy::Rule with the +policies+ policies.
31
+ def emit_ruleset(rules, policies)
32
32
  parts = []
33
33
  parts << emit_header
34
34
  parts << raw_ruleset(raw_rules(rules))
35
35
  parts << nat_ruleset(nat_rules(rules))
36
- parts << filter_ruleset(filter_rules(rules), policy)
36
+ parts << filter_ruleset(filter_rules(rules), policies)
37
37
  ruleset = parts.flatten.compact.join("\n")
38
38
  "#{ruleset}\n"
39
39
  end
@@ -61,14 +61,14 @@ module Puffy
61
61
  parts
62
62
  end
63
63
 
64
- def filter_ruleset(rules, policy)
64
+ def filter_ruleset(rules, policies)
65
65
  return unless rules.any?
66
66
 
67
67
  parts = ['*filter']
68
- parts << emit_chain_policies(input: policy, forward: policy, output: policy)
69
- parts << input_filter_ruleset(rules)
70
- parts << forward_filter_ruleset(rules)
71
- parts << output_filter_rulset(rules)
68
+ parts << emit_chain_policies(input: policies.dig(:in, :action), forward: policies.dig(:in, :action), output: policies.dig(:out, :action))
69
+ parts << input_filter_ruleset(rules, policies)
70
+ parts << forward_filter_ruleset(rules, policies)
71
+ parts << output_filter_rulset(rules, policies)
72
72
  parts << 'COMMIT'
73
73
  parts
74
74
  end
@@ -77,20 +77,32 @@ module Puffy
77
77
  policies.map { |chain, action| ":#{chain.upcase} #{Puffy::Formatters::Iptables.iptables_action(action)} [0:0]" }
78
78
  end
79
79
 
80
- def input_filter_ruleset(rules)
81
- parts = ['-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT']
80
+ def input_filter_ruleset(rules, policies)
81
+ parts = [
82
+ '-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT',
83
+ '-A INPUT -m conntrack --ctstate INVALID -j DROP',
84
+ ]
82
85
  parts << input_filter_rules(rules).map { |rule| @rule_formatter.emit_rule(rule) }
86
+ parts << '-A INPUT -j LOG' if policies.dig(:in, :log)
87
+ parts
83
88
  end
84
89
 
85
- def forward_filter_ruleset(rules)
86
- parts = ['-A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT']
87
- parts << rules.select(&:fwd?).map { |rule| @rule_formatter.emit_rule(rule) }
88
- parts << rules.select { |r| r.rdr? && !Puffy::Formatters::Base.loopback_addresses.include?(r.rdr_to_host) }.map { |rule| @rule_formatter.emit_rule(Puffy::Rule.fwd_rule(rule)) }
90
+ def forward_filter_ruleset(rules, policies)
91
+ parts = [
92
+ '-A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT',
93
+ '-A FORWARD -m conntrack --ctstate INVALID -j DROP',
94
+ ]
95
+ parts << fwd_filter_rules(rules).map { |rule| @rule_formatter.emit_rule(rule) }
96
+ parts << rdr_filter_rules(rules).map { |rule| @rule_formatter.emit_rule(Puffy::Rule.fwd_rule(rule)) }
97
+ parts << '-A FORWARD -j LOG' if policies.dig(:in, :log)
98
+ parts
89
99
  end
90
100
 
91
- def output_filter_rulset(rules)
101
+ def output_filter_rulset(rules, policies)
92
102
  parts = ['-A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT']
93
103
  parts << output_filter_rules(rules).map { |rule| @rule_formatter.emit_rule(rule) }
104
+ parts << '-A OUTPUT -j LOG' if policies.dig(:out, :log)
105
+ parts
94
106
  end
95
107
 
96
108
  def raw_rules(rules)
@@ -113,6 +125,14 @@ module Puffy
113
125
  end
114
126
  end
115
127
 
128
+ def fwd_filter_rules(rules)
129
+ rules.select(&:fwd?)
130
+ end
131
+
132
+ def rdr_filter_rules(rules)
133
+ rules.select { |r| r.rdr? && !Puffy::Formatters::Base.loopback_addresses.include?(r.rdr_to_host) }
134
+ end
135
+
116
136
  def output_filter_rules(rules)
117
137
  rules.select { |r| r.filter? && r.out? }.map do |rule|
118
138
  dup = rule.dup
@@ -5,9 +5,9 @@ module Puffy
5
5
  module Iptables4 # :nodoc:
6
6
  # IPv4 Iptables implementation of a Puffy Ruleset formatter.
7
7
  class Ruleset < Puffy::Formatters::Iptables::Ruleset # :nodoc:
8
- # Return an IPv4 Iptables 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)
8
+ # Return an IPv4 Iptables String representation of the provided +rules+ Puffy::Rule with the +policies+ policies.
9
+ def emit_ruleset(rules, policies)
10
+ super(rules.select(&:ipv4?), policies)
11
11
  end
12
12
 
13
13
  def filename_fragment
@@ -5,9 +5,9 @@ module Puffy
5
5
  module Iptables6 # :nodoc:
6
6
  # IPv6 Iptables implementation of a Puffy Ruleset formatter.
7
7
  class Ruleset < Puffy::Formatters::Iptables::Ruleset # :nodoc:
8
- # Return an IPv6 Iptables 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)
8
+ # Return an IPv6 Iptables String representation of the provided +rules+ Puffy::Rule with the +policies+ policies.
9
+ def emit_ruleset(rules, policies)
10
+ super(rules.select(&:ipv6?), policies)
11
11
  end
12
12
 
13
13
  def filename_fragment
@@ -6,10 +6,10 @@ module Puffy
6
6
  # Pf implementation of a Puffy Ruleset formatter.
7
7
  class Ruleset < Puffy::Formatters::Base::Ruleset # :nodoc:
8
8
  # Returns a Pf String representation of the provided +rules+ Array of Puffy::Rule.
9
- def emit_ruleset(rules, policy = :block)
9
+ def emit_ruleset(rules, policies)
10
10
  parts = []
11
11
 
12
- parts << emit_header(policy)
12
+ parts << emit_header(policies)
13
13
 
14
14
  parts << super(rules.select(&:nat?))
15
15
  parts << super(rules.select(&:rdr?))
@@ -23,12 +23,14 @@ module Puffy
23
23
  ['pf', 'pf.conf']
24
24
  end
25
25
 
26
- def emit_header(policy)
26
+ def emit_header(policies)
27
27
  parts = super()
28
28
  parts << 'match in all scrub (no-df)'
29
29
  parts << 'set skip on lo'
30
- parts << @rule_formatter.emit_rule(Puffy::Rule.new(action: policy, dir: :in, no_quick: true))
31
- parts << @rule_formatter.emit_rule(Puffy::Rule.new(action: policy, dir: :out, no_quick: true))
30
+ %i[in out].each do |direction|
31
+ policy = policies[direction]
32
+ parts << @rule_formatter.emit_rule(Puffy::Rule.new(action: policy[:action], log: policy[:log], dir: direction, no_quick: true))
33
+ end
32
34
  parts
33
35
  end
34
36
  end
@@ -40,6 +42,7 @@ module Puffy
40
42
  parts = []
41
43
  parts << emit_action(rule)
42
44
  parts << emit_direction(rule)
45
+ parts << emit_log(rule)
43
46
  parts << emit_quick(rule)
44
47
  parts << emit_on(rule)
45
48
  parts << emit_what(rule)
@@ -62,6 +65,10 @@ module Puffy
62
65
  'quick' unless rule.no_quick
63
66
  end
64
67
 
68
+ def emit_log(rule)
69
+ 'log' if rule.log
70
+ end
71
+
65
72
  def emit_on(rule)
66
73
  "on #{rule.on.gsub('!', '! ')}" if rule.on
67
74
  end
@@ -116,13 +123,21 @@ module Puffy
116
123
  def emit_rdr_to(rule)
117
124
  return unless rule.rdr?
118
125
 
119
- keyword = Puffy::Formatters::Base.loopback_addresses.include?(rule.rdr_to_host) ? 'divert-to' : 'rdr-to'
126
+ keyword = rdr_to_keyword(rule)
120
127
  destination = rule.rdr_to_host || loopback_address(rule.af)
121
128
  raise 'Unspecified address family' if destination.nil?
122
129
 
123
130
  emit_endpoint_specification(keyword, destination, rule.rdr_to_port)
124
131
  end
125
132
 
133
+ def rdr_to_keyword(rule)
134
+ if Puffy::Formatters::Base.loopback_addresses.include?(rule.rdr_to_host)
135
+ 'divert-to'
136
+ else
137
+ 'rdr-to'
138
+ end
139
+ end
140
+
126
141
  def emit_nat_to(rule)
127
142
  "nat-to #{emit_address(rule.nat_to)}" if rule.nat_to
128
143
  end