reyes 0.3.1 → 1.0.0

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,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NzRmNzQ2MDEyZGUzZDZlNDZmNzlkMTM5MDkxN2UwZGYwYWI2MjFmOA==
4
+ MmU1NmFhNTQzMDg4ZTgzMjJhMjQyNzFmYzlkYmNhN2VjMjM4MzA1Yg==
5
5
  data.tar.gz: !binary |-
6
- YjFkZTIyM2JhNTM4ODgxMDgwN2JjYjNlZWEyYjM1OWQxN2E3ZmRlOA==
6
+ MjkyYWNkY2RmMDI4NTgzMDcyYTkwNDg5MjI0YTdlYzExNDJiZmQ5OA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MzYzNGY5ZThkMTJjYTI5NDM0ODgwZThlZGQwNTJlMDFjNzkwZjU3ZDM5Mjkw
10
- NjE4ZGJlOTE0MGM4NmI0NjIyNjFkZDE5ZDY3YzBlOWY3Y2RkNGQxMDliMDdi
11
- NDk3MDlkYmM1YzYxOWU3NGUxODNiYjc0YWFkNGIzMThiMzAwM2U=
9
+ Yzg3MjRiMzc2MjZhOTIyZTRmOGRlYTU3OTJjNjk0MjU5ZDU5MzhjMzhhMjll
10
+ MGNhZTEzMmJiMjRhZTc2MjY5OWY2YzE0NTJmNjA4ZmM0NTU0MzAxNmU3NTEx
11
+ ZjI5NWYxMDdmYWI2ZDI4NmZmZjE0MTIwYjI3ZGQ3MDFjYjE4MDQ=
12
12
  data.tar.gz: !binary |-
13
- NDVjZGM1NWFlODI2YzE4OTI2YjgwMDBiNTg1Yjg0MzY4YTc4NmFlOTRhODEy
14
- Yjk3MWQyZmQ4YjkyMTk0OGUwZjczZTRhNGYyMjJkNDU0M2MyN2VkZmQxMDZk
15
- ZGE3OTY0MjQxNjczYzRiMjkyNDA2YjgzMDUwNjVhMGRjMDc4M2U=
13
+ ZjRkMDg4NzlmN2ViNDNlOTZiN2IzNzU1M2I0ZmVlM2YzZmJhMzYxY2NiYzA1
14
+ M2UzMzgzZDkyZDBhYzM4ZWViMzRlOGU1MjQ3ODJlMTc5MGQ2MjQwYTdkOTk5
15
+ YTZlMDM3ZGQzYjNkYjQ2OTI3ODJiMGE5YjE3OTUyMmNkYjdhNmQ=
@@ -352,7 +352,7 @@ module Reyes
352
352
  [
353
353
  RegionShortNames.fetch(region),
354
354
  group.group_id,
355
- group.name,
355
+ group.name.gsub(/[^a-zA-Z0-9\._\/,@+=-]/, '_'),
356
356
  ].join(':')[0...31]
357
357
  end
358
358
 
@@ -1,12 +1,12 @@
1
1
  module Reyes
2
2
  class Diff
3
3
  def initialize
4
- @old = Tempfile.new('old')
5
- @new = Tempfile.new('new')
4
+ @old = Tempfile.new('diff.old.')
5
+ @new = Tempfile.new('diff.new.')
6
6
  end
7
7
 
8
8
  # Consumes the +Diff+, returning the full unified diff of @old and @new
9
- # @return [String]
9
+ # @return [String, nil] String diff or nil if the files do not differ
10
10
  def diff
11
11
  raise "Diff has already been created" unless @old && @new
12
12
 
@@ -14,8 +14,22 @@ module Reyes
14
14
  f.flush
15
15
  end
16
16
 
17
- Subprocess.call(["diff", '-u', @old.path, @new.path], :stdout => Subprocess::PIPE) do |c|
18
- return c.communicate
17
+ output = nil
18
+ cmd = ["diff", '-u', @old.path, @new.path]
19
+ status = Subprocess.call(cmd, :stdout => Subprocess::PIPE) do |c|
20
+ output, _ = c.communicate
21
+ end
22
+
23
+ case status.exitstatus
24
+ when 0
25
+ # no diff
26
+ return nil
27
+ when 1
28
+ # files differ
29
+ return output
30
+ else
31
+ # trouble
32
+ raise Subprocess::NonZeroExit.new(cmd, status)
19
33
  end
20
34
  ensure
21
35
  @old.unlink
@@ -5,15 +5,19 @@ module Reyes
5
5
  include Chalk::Log
6
6
 
7
7
  # @param data [Hash]
8
- def initialize(data)
8
+ # @param assert_version [Boolean]
9
+ def initialize(data, assert_version=true)
9
10
  @data = data
10
11
  log.info("Initialized FakeAws with metadata: #{metadata.inspect}")
11
12
 
12
13
  version = metadata['format_version']
13
14
  if version != Reyes::JSON_FORMAT_VERSION
14
- log.error("WARNING: JSON format_version #{version.inspect} " \
15
- "differs from our version #{Reyes::JSON_FORMAT_VERSION}")
16
- log.error('Proceeding anyway...')
15
+ msg = "JSON format_version #{version.inspect} " \
16
+ "differs from our version #{Reyes::JSON_FORMAT_VERSION}"
17
+ log.error('WARNING: ' + msg)
18
+ if assert_version
19
+ raise Error.new(msg)
20
+ end
17
21
  end
18
22
  end
19
23
 
@@ -6,7 +6,7 @@ module Reyes
6
6
  class GroupManager
7
7
  include Chalk::Log
8
8
 
9
- ReyesInputChain = 'reyes-ipsec-input'
9
+ ReyesInputChain = 'reyes-input'
10
10
 
11
11
  attr_reader :fake_aws, :instance_id
12
12
 
@@ -283,27 +283,24 @@ module Reyes
283
283
  lines << ''
284
284
 
285
285
  lines << ":#{ReyesInputChain} -"
286
- lines << ':reyes-log-drop -'
287
- lines << ':reyes-log-accept -'
288
286
  lines << ':reyes-accept -'
289
287
  lines << ':reyes-drop -'
290
- lines << ''
291
-
292
- lines << IPTables.log_rule_string('reyes-log-drop', 'REYES BLOCK')
293
- lines << IPTables.log_rule_string('reyes-log-accept', 'REYES ACCEPT')
294
-
295
- lines << '-A reyes-drop -j reyes-log-drop' if log_drop
296
- lines << '-A reyes-drop -j DROP'
297
- lines << '-A reyes-accept -j reyes-log-accept' if log_accept
298
- lines << '-A reyes-accept -j ACCEPT'
288
+ lines << ':reyes-log-accept -'
289
+ lines << ':reyes-log-drop -'
299
290
 
300
291
  # add rules to direct appropriate traffic into reyes
301
292
  lines << ''
302
- lines << '# input chain rules'
293
+ lines << '## input chain rules'
303
294
  lines.concat(input_chain_rules)
304
295
 
305
296
  lines << ''
306
- lines << '# static global rules'
297
+ lines << '-A reyes-accept -j reyes-log-accept' if log_accept
298
+ lines << '-A reyes-accept -j ACCEPT'
299
+ lines << '-A reyes-drop -j reyes-log-drop' if log_drop
300
+ lines << '-A reyes-drop -j DROP'
301
+
302
+ lines << ''
303
+ lines << '## static global rules'
307
304
 
308
305
  # allow normal ICMP traffic
309
306
  IPTables.innocuous_icmp_rules(ReyesInputChain).each do |r|
@@ -320,16 +317,21 @@ module Reyes
320
317
 
321
318
  # add dynamic rules
322
319
  lines << ''
323
- lines << '# dynamic rules from security groups'
320
+ lines << '## dynamic rules from security groups'
324
321
  dynamic_rules_from_data(data).each do |rule|
325
322
  lines << rule
326
323
  end
327
324
 
328
- # add reyes-drop to very end of reyes-ipsec-input chain
325
+ # add reyes-drop to very end of reyes-input chain
329
326
  lines << ''
330
- lines << '# default drop'
327
+ lines << '## default drop'
331
328
  lines << "-A #{ReyesInputChain} -j reyes-drop"
332
329
 
330
+ lines << ''
331
+ lines << '## log rules'
332
+ lines << IPTables.log_rule_string('reyes-log-accept', 'REYES ACCEPT')
333
+ lines << IPTables.log_rule_string('reyes-log-drop', 'REYES BLOCK')
334
+
333
335
  # commit the filter table
334
336
  lines << ''
335
337
  lines << 'COMMIT'
@@ -3,6 +3,9 @@ module Reyes
3
3
  TYPE = "hash:ip"
4
4
  attr_reader :name, :members
5
5
 
6
+ # TODO: add more useful logging
7
+ include Chalk::Log
8
+
6
9
  # Constructor for ipsets, maintaining the invariant that once constructed,
7
10
  # ipsets will not be altered.
8
11
  # @param [String] name of the IPSet to create
@@ -21,6 +24,7 @@ module Reyes
21
24
  # Builds the ipset, retuning an IPSet
22
25
  # @returns [IPSet]
23
26
  def build
27
+ log.info("Building ipset #{@name.inspect}")
24
28
  create
25
29
  populate
26
30
  IPSet.load(@name)
@@ -42,7 +42,7 @@ module Reyes
42
42
 
43
43
  if dport_range.first == dport_range.last
44
44
  # single port match
45
- cmd += ['--dport', dport_range.first.to_s]
45
+ cmd += ['-m', protocol.to_s, '--dport', dport_range.first.to_s]
46
46
  else
47
47
  # port range match
48
48
  cmd += ['-m', 'multiport', '--dports',
@@ -2,6 +2,8 @@ module Reyes
2
2
  class RunManager
3
3
  include Chalk::Log
4
4
 
5
+ IPSET_NAME_PATTERN = /(\d+)(?<nogen>:(\w+):(sg-[a-f0-9]{8}):(\w+))/
6
+
5
7
  def initialize(group_manager)
6
8
  @group_manager = group_manager
7
9
  end
@@ -29,7 +31,7 @@ module Reyes
29
31
  data = @group_manager.generate_rules
30
32
  end
31
33
 
32
- log.info("Finished loading/generating data")
34
+ log.info("Finished RunManager.generate_data!")
33
35
 
34
36
  data
35
37
  end
@@ -83,13 +85,15 @@ module Reyes
83
85
  iptables_restore(new_rules)
84
86
 
85
87
  # XXX(richo) Should we be pruning inside run! ?
86
- log.info('Finished applying data')
88
+ log.info('Finished RunManager.apply_data!')
87
89
  end
88
90
 
89
91
  def materialize_ipsets(new_ipsets)
92
+ log.info('Materializing ipsets')
90
93
  new_ipsets.each do |ipset|
91
94
  ipset.build
92
95
  end
96
+ log.info('Done building ipsets')
93
97
  end
94
98
 
95
99
  # Call iptables-restore to atomically restore a set of iptables rules.
@@ -151,20 +155,27 @@ module Reyes
151
155
  # @param new_rules [String]
152
156
  #
153
157
  def show_iptables_diff(new_rules)
158
+ log.debug('show_iptables_diff')
159
+
160
+ log.debug('+ iptables-save -t filter')
161
+ current = Subprocess.check_output(%w{iptables-save -t filter})
162
+
154
163
  diff = Diff.new
155
- diff.old.puts(Subprocess.check_output(%w{iptables-save}))
156
- diff.new.puts(new_rules)
164
+ diff.old.puts(filter_iptables_output(current))
165
+ diff.new.puts(filter_iptables_output(new_rules))
157
166
 
158
- log.info "Proposed IPTables diff:"
159
- puts diff.diff
167
+ log.info 'Proposed IPTables diff:'
168
+ log.info(diff.diff || '<unchanged>')
160
169
  end
161
170
 
162
171
  def show_ipsets_diff(new_ipsets)
172
+ log.debug('show_ipsets_diff')
173
+
163
174
  diff = Diff.new
164
175
 
165
176
  dump = lambda do |f, ipset|
166
177
  ipset.sort_by(&:name).each do |ip|
167
- f.puts(ip.name)
178
+ f.puts(gsub_ipset_generation(ip.name))
168
179
  ip.members.sort.each do |m|
169
180
  f.puts("\t#{m}")
170
181
  end
@@ -174,8 +185,26 @@ module Reyes
174
185
  dump.call(diff.old, Reyes::IPSet.load_all)
175
186
  dump.call(diff.new, new_ipsets)
176
187
 
177
- log.info "Proposed IPSets diff:"
178
- puts diff.diff
188
+ log.info 'Proposed IPSets diff:'
189
+ log.info(diff.diff || '<unchanged>')
190
+ end
191
+
192
+ private
193
+
194
+ # Use `IPSET_NAME_PATTERN` to remove generation numbers from any matching
195
+ # ipset names in the input.
196
+ #
197
+ # @param input [String]
198
+ # @return [String]
199
+ #
200
+ def gsub_ipset_generation(input)
201
+ input.gsub(IPSET_NAME_PATTERN) { '##' + Regexp.last_match['nogen'] }
202
+ end
203
+
204
+ def filter_iptables_output(input)
205
+ gsub_ipset_generation(input).each_line.reject { |line|
206
+ line.strip.empty? || line.start_with?('##')
207
+ }.join
179
208
  end
180
209
  end
181
210
  end
@@ -1,6 +1,6 @@
1
1
  module Reyes
2
2
  # The Reyes version number
3
- VERSION = '0.3.1' unless defined?(self::VERSION)
3
+ VERSION = '1.0.0' unless defined?(self::VERSION)
4
4
 
5
5
  # Number defining the JSON serialization format
6
6
  JSON_FORMAT_VERSION = 2 unless defined?(self::JSON_FORMAT_VERSION)
@@ -24,6 +24,7 @@ Gem::Specification.new do |gem|
24
24
 
25
25
  TO DO
26
26
  EOM
27
+ # TODO ^
27
28
  gem.homepage = "https://github.com/stripe/reyes/"
28
29
 
29
30
  gem.files = list_files
@@ -35,8 +36,8 @@ Gem::Specification.new do |gem|
35
36
  gem.version = Reyes::VERSION
36
37
 
37
38
  gem.add_dependency 'aws-sdk', '~> 1.60'
38
- gem.add_dependency 'chalk-log'
39
- gem.add_dependency 'subprocess'
39
+ gem.add_dependency 'chalk-log', '~> 0.1'
40
+ gem.add_dependency 'subprocess', '~> 1.2'
40
41
 
41
42
  gem.add_development_dependency 'pry'
42
43
  gem.add_development_dependency 'rake'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reyes
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Brody
@@ -29,30 +29,30 @@ dependencies:
29
29
  name: chalk-log
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - ! '>='
32
+ - - ~>
33
33
  - !ruby/object:Gem::Version
34
- version: '0'
34
+ version: '0.1'
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - ! '>='
39
+ - - ~>
40
40
  - !ruby/object:Gem::Version
41
- version: '0'
41
+ version: '0.1'
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: subprocess
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - ! '>='
46
+ - - ~>
47
47
  - !ruby/object:Gem::Version
48
- version: '0'
48
+ version: '1.2'
49
49
  type: :runtime
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - ! '>='
53
+ - - ~>
54
54
  - !ruby/object:Gem::Version
55
- version: '0'
55
+ version: '1.2'
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: pry
58
58
  requirement: !ruby/object:Gem::Requirement