reyes 0.3.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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