veracode 1.0.0.alpha
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.
- data/bin/veracode +81 -0
- data/lib/veracode.rb +739 -0
- data/lib/veracode/version.rb +3 -0
- metadata +60 -0
data/bin/veracode
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
|
4
|
+
$:.unshift File.expand_path(File.dirname(__FILE__) + "/../lib")
|
5
|
+
$:.unshift Dir.pwd
|
6
|
+
|
7
|
+
unless File.exists?("script/rails")
|
8
|
+
$stderr.puts "Current directory #{File.basename(Dir.pwd).dump} does not appear to be a Rails 3 application."
|
9
|
+
exit
|
10
|
+
end
|
11
|
+
APP_PATH = File.expand_path('config/application')
|
12
|
+
APP_NAME = File.basename(Dir.pwd)
|
13
|
+
COMMAND = "#{$0} #{ARGV.join(' ')}"
|
14
|
+
|
15
|
+
require 'veracode'
|
16
|
+
|
17
|
+
$options = {
|
18
|
+
:phase1 => false,
|
19
|
+
:phase2 => false,
|
20
|
+
:phase3 => true,
|
21
|
+
:archive_source => true,
|
22
|
+
:include_inherited => false,
|
23
|
+
:jruby => false,
|
24
|
+
}
|
25
|
+
|
26
|
+
subcommand = ARGV.shift
|
27
|
+
case subcommand
|
28
|
+
when "prepare", "prep"
|
29
|
+
OptionParser.new do |opts|
|
30
|
+
opts.banner = "Usage: veracode prepare [options]"
|
31
|
+
|
32
|
+
opts.on("-v", "--verbose", "Run verbosely") do
|
33
|
+
$options[:verbose] = true
|
34
|
+
end
|
35
|
+
|
36
|
+
opts.on("-a", "--all", "Archive objects at all stages") do
|
37
|
+
$options[:phase1] = true
|
38
|
+
$options[:phase2] = true
|
39
|
+
end
|
40
|
+
|
41
|
+
opts.on("-f", "--file", "Disassemble .rb files") do
|
42
|
+
$options[:disasm] = true
|
43
|
+
end
|
44
|
+
|
45
|
+
opts.on("-j", "--jruby", "Force JRuby mode") do
|
46
|
+
$options[:jruby] = true
|
47
|
+
end
|
48
|
+
|
49
|
+
opts.on("--[no-]source", "[Don't] Include source code in archive") do |s|
|
50
|
+
$options[:archive_source] = s
|
51
|
+
end
|
52
|
+
|
53
|
+
opts.on("-D", "--debug", "Enable debug output") do
|
54
|
+
$DEBUG = true
|
55
|
+
end
|
56
|
+
|
57
|
+
end.parse!
|
58
|
+
|
59
|
+
Veracode.prepare
|
60
|
+
|
61
|
+
when "help", nil
|
62
|
+
ARGV.clear
|
63
|
+
ARGV.unshift "--help"
|
64
|
+
|
65
|
+
OptionParser.new do |opts|
|
66
|
+
opts.banner = "Usage: veracode prepare [options]"
|
67
|
+
end.parse!
|
68
|
+
|
69
|
+
else
|
70
|
+
$stderr.puts "#{subcommand.dump} is not a valid subcommand"
|
71
|
+
|
72
|
+
ARGV.clear
|
73
|
+
ARGV.unshift "--help"
|
74
|
+
|
75
|
+
OptionParser.new do |opts|
|
76
|
+
opts.banner = "Usage: veracode prepare [options]"
|
77
|
+
end.parse!
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
|
data/lib/veracode.rb
ADDED
@@ -0,0 +1,739 @@
|
|
1
|
+
require 'zlib'
|
2
|
+
require 'zip/zip'
|
3
|
+
require "veracode/version"
|
4
|
+
|
5
|
+
module Veracode
|
6
|
+
@run_id = nil
|
7
|
+
|
8
|
+
# Metadata and method disassemblies for all Modules (.txt.gz)
|
9
|
+
@disasmlog = nil
|
10
|
+
@disasmlog_filename = "disasm.txt.gz"
|
11
|
+
|
12
|
+
# Error log including capture of STDERR and any errors generated by the gem (.log)
|
13
|
+
@errorlog = nil
|
14
|
+
@errorlog_filename = "error.log"
|
15
|
+
|
16
|
+
# Index file containing the names of files present in the application directory (.txt)
|
17
|
+
@index_filename = "index.txt"
|
18
|
+
|
19
|
+
# Manifest file containing original names of all files in archive (.txt)
|
20
|
+
@manifest = []
|
21
|
+
@manifest_filename = "manifest.txt"
|
22
|
+
|
23
|
+
# The final archive that will be uploaded to Veracode for analysis (.zip)
|
24
|
+
@archive = nil
|
25
|
+
@archive_filename = nil
|
26
|
+
@archive_dirname = nil
|
27
|
+
|
28
|
+
|
29
|
+
def self.init
|
30
|
+
@run_id = Time.now.strftime("%Y%m%d%H%M%S")
|
31
|
+
@archive_dirname = File.join("tmp","veracode-#{@run_id}")
|
32
|
+
|
33
|
+
if !Dir.exists?("tmp")
|
34
|
+
begin
|
35
|
+
Dir.mkdir("tmp")
|
36
|
+
rescue Exception => e
|
37
|
+
$stderr.puts "Directory 'tmp' does not exist and cannot be created: #{e.message}"
|
38
|
+
exit
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
while Dir.exists?(@archive_dirname)
|
43
|
+
@run_id = Time.now.strftime("%Y%m%d%H%M%S")
|
44
|
+
@archive_dirname = File.join("tmp","veracode-#{@run_id}")
|
45
|
+
end
|
46
|
+
|
47
|
+
begin
|
48
|
+
Dir.mkdir(@archive_dirname)
|
49
|
+
rescue Exception => e
|
50
|
+
$stderr.puts "Unable to make directory #{@archive_dirname}: #{e.message}"
|
51
|
+
exit
|
52
|
+
end
|
53
|
+
|
54
|
+
@archive_filename = File.join("tmp","veracode-#{APP_NAME}-#{@run_id}.zip")
|
55
|
+
|
56
|
+
@errorlog_filename = File.join(@archive_dirname, @errorlog_filename)
|
57
|
+
@disasmlog_filename = File.join(@archive_dirname, @disasmlog_filename)
|
58
|
+
@index_filename = File.join(@archive_dirname, @index_filename)
|
59
|
+
@manifest_filename = File.join(@archive_dirname, @manifest_filename)
|
60
|
+
|
61
|
+
# Try touching each of the files to be written
|
62
|
+
[@disasmlog_filename, @errorlog_filename, @index_filename, @manifest_filename].each {|f|
|
63
|
+
begin
|
64
|
+
File.open(f, "wb") {}
|
65
|
+
rescue Exception => e
|
66
|
+
$stderr.puts "Unable to create file #{f}: #{e.message}"
|
67
|
+
exit
|
68
|
+
else
|
69
|
+
@manifest << f
|
70
|
+
end
|
71
|
+
}
|
72
|
+
|
73
|
+
begin
|
74
|
+
@errorlog = File.open(@errorlog_filename, "wb")
|
75
|
+
log_error "COMMAND: #{COMMAND}"
|
76
|
+
log_error "RUBY_DESCRIPTION: #{RUBY_DESCRIPTION}"
|
77
|
+
log_error "RAILS_VERSION: " + `rails --version`.chomp
|
78
|
+
log_error "GEM_VERSION: #{Veracode::VERSION}"
|
79
|
+
log_error "PWD: #{Dir.pwd.to_s.dump}"
|
80
|
+
log_error "APP_NAME: #{APP_NAME.dump}"
|
81
|
+
log_error "RUNID: #{@run_id}"
|
82
|
+
rescue Exception => e
|
83
|
+
$stderr.puts "Unable to create errorlog #{@errorlog_filename}: #{e.message}"
|
84
|
+
@errorlog = $stderr
|
85
|
+
else
|
86
|
+
STDERR.reopen(@errorlog)
|
87
|
+
end
|
88
|
+
|
89
|
+
index_application
|
90
|
+
|
91
|
+
@manifest += Dir.glob("*").keep_if {|f| File.file?(f)}
|
92
|
+
|
93
|
+
# {app config db doc lib log public script test tmp vendor}
|
94
|
+
%w{app config lib log public script vendor}.each {|dirname|
|
95
|
+
@manifest += Dir[File.join(dirname, "**", "*")].keep_if {|f| File.file?(f)}
|
96
|
+
}
|
97
|
+
@manifest += Dir[File.join("db", "**", "*.rb")]
|
98
|
+
|
99
|
+
if $options[:archive_source]
|
100
|
+
# Add any other ruby files not already added
|
101
|
+
@manifest |= Dir[File.join("**","*.rb")]
|
102
|
+
# Add any other erb files not already added
|
103
|
+
@manifest |= Dir[File.join("**","*.erb")]
|
104
|
+
# Add any other haml files not already added
|
105
|
+
@manifest |= Dir[File.join("**","*.haml")]
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.index_application
|
111
|
+
File.open(@index_filename, "wb") {|index_file|
|
112
|
+
Dir[File.join("**","*")].keep_if {|f| File.file?(f)}.sort.each {|f|
|
113
|
+
index_file.puts f.dump
|
114
|
+
}
|
115
|
+
}
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.pack_manifest
|
119
|
+
|
120
|
+
puts "Archiving disassembly and source files"
|
121
|
+
|
122
|
+
begin
|
123
|
+
File.open(@manifest_filename, "wb") { |mf|
|
124
|
+
@manifest.sort.each { |f|
|
125
|
+
mf.puts f.to_s.dump
|
126
|
+
}
|
127
|
+
}
|
128
|
+
rescue Exception => e
|
129
|
+
log_error e.message
|
130
|
+
$stderr.puts "Unable to write manifest file #{@manifest_filename}: #{e.message}"
|
131
|
+
end
|
132
|
+
|
133
|
+
@errorlog.flush
|
134
|
+
|
135
|
+
begin
|
136
|
+
Zip::ZipFile.open(@archive_filename, Zip::ZipFile::CREATE) { |zf|
|
137
|
+
@manifest.each {|file|
|
138
|
+
|
139
|
+
if file.start_with?(@archive_dirname)
|
140
|
+
name_in_archive = file.sub(/^#{@archive_dirname + File::SEPARATOR}/,"")
|
141
|
+
else
|
142
|
+
name_in_archive = File.join(APP_NAME, file)
|
143
|
+
end
|
144
|
+
|
145
|
+
puts "Adding #{file} to archive as #{name_in_archive}" if $options[:verbose]
|
146
|
+
zf.add(name_in_archive, file)
|
147
|
+
}
|
148
|
+
}
|
149
|
+
rescue Exception => e
|
150
|
+
$stderr.puts "Unable to create archive #{@manifest_filename}: #{e.message}"
|
151
|
+
exit
|
152
|
+
end
|
153
|
+
|
154
|
+
puts "Please upload #{@archive_filename}"
|
155
|
+
end
|
156
|
+
|
157
|
+
def self.cleanup
|
158
|
+
[@disasmlog_filename, @errorlog_filename, @index_filename, @manifest_filename].each {|f|
|
159
|
+
begin
|
160
|
+
File.delete(f)
|
161
|
+
rescue Exception => e
|
162
|
+
log_error "Unable to delete #{f.to_s.dump} (#{e.message})"
|
163
|
+
end
|
164
|
+
}
|
165
|
+
|
166
|
+
begin
|
167
|
+
Dir.delete(@archive_dirname)
|
168
|
+
rescue Exception => e
|
169
|
+
puts "Unable to remove #{@archive_dirname.to_s.dump} (#{e.message})"
|
170
|
+
log_error "Unable to remove #{@archive_dirname.to_s.dump} (#{e.message})"
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def self.baseline
|
175
|
+
self.update
|
176
|
+
@baseline_objects = @objects
|
177
|
+
@baseline_modules = @modules
|
178
|
+
@baseline_classes = @classes
|
179
|
+
end
|
180
|
+
|
181
|
+
def self.rebaseline
|
182
|
+
self.baseline
|
183
|
+
end
|
184
|
+
|
185
|
+
def self.update
|
186
|
+
@objects = ObjectSpace.each_object.to_a
|
187
|
+
@modules = ObjectSpace.each_object(Module).to_a
|
188
|
+
@classes = ObjectSpace.each_object(Class).to_a
|
189
|
+
end
|
190
|
+
|
191
|
+
def self.stats
|
192
|
+
puts "#{ObjectSpace.each_object.count.to_s} objects"
|
193
|
+
puts "#{ObjectSpace.each_object(Module).count.to_s} modules"
|
194
|
+
puts "#{ObjectSpace.each_object(Class).count.to_s} classes"
|
195
|
+
puts
|
196
|
+
end
|
197
|
+
|
198
|
+
|
199
|
+
##############################################################################
|
200
|
+
# Helpers
|
201
|
+
def self.glob_require(files)
|
202
|
+
Dir.glob(files) do |f|
|
203
|
+
print "Requiring #{f.to_s} " if $options[:verbose]
|
204
|
+
|
205
|
+
begin
|
206
|
+
require File.expand_path(f)
|
207
|
+
rescue Exception => e
|
208
|
+
puts "(failed: #{e.message})" if $options[:verbose]
|
209
|
+
log_error "Unable to require #{File.expand_path(f).to_s.dump} (#{e.message})"
|
210
|
+
else
|
211
|
+
puts "(OK)" if $options[:verbose]
|
212
|
+
end
|
213
|
+
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def self.safe_name(o)
|
218
|
+
case
|
219
|
+
when o == ActiveSupport::TimeWithZone
|
220
|
+
"ActiveSupport::TimeWithZone"
|
221
|
+
when o.is_a?(Module)
|
222
|
+
( o.name.nil? ? o.to_s : o.name )
|
223
|
+
when o.is_a?(Method), o.is_a?(UnboundMethod)
|
224
|
+
o.name.to_s
|
225
|
+
else
|
226
|
+
o.to_s
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
def self.quote(o)
|
231
|
+
o.to_s.dump
|
232
|
+
end
|
233
|
+
|
234
|
+
def self.quote_if_string(o)
|
235
|
+
( o.is_a?(String) ? o.dump : o.inspect )
|
236
|
+
end
|
237
|
+
|
238
|
+
def self.good_type?(o)
|
239
|
+
%w{
|
240
|
+
Array
|
241
|
+
Bignum
|
242
|
+
Class
|
243
|
+
FalseClass
|
244
|
+
Fixnum
|
245
|
+
Float
|
246
|
+
Hash
|
247
|
+
Module
|
248
|
+
NilClass
|
249
|
+
Range
|
250
|
+
Rational
|
251
|
+
Regexp
|
252
|
+
String
|
253
|
+
Symbol
|
254
|
+
Time
|
255
|
+
TrueClass
|
256
|
+
}.include?(o.class.to_s)
|
257
|
+
end
|
258
|
+
|
259
|
+
def self.safe_inspect(o)
|
260
|
+
if o.is_a?(Array)
|
261
|
+
"[" +
|
262
|
+
o.map {|i| safe_inspect(i) }.join(", ") +
|
263
|
+
"]"
|
264
|
+
elsif o.is_a?(Hash)
|
265
|
+
"{" +
|
266
|
+
o.map {|k,v| "#{safe_inspect(k)}=>#{safe_inspect(v)}" }.join(", ") +
|
267
|
+
"}"
|
268
|
+
elsif o.is_a?(Module)
|
269
|
+
safe_name(o)
|
270
|
+
elsif good_type?(o)
|
271
|
+
quote_if_string(o)
|
272
|
+
else
|
273
|
+
":veracode_nil" # not a white-listed type
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
def self.log_error(data)
|
278
|
+
@errorlog.printf "veracode [%s] %s\n", Time.now.to_s, data.to_s.chomp
|
279
|
+
end
|
280
|
+
|
281
|
+
|
282
|
+
##############################################################################
|
283
|
+
# Archiving
|
284
|
+
def self.prepare_archive
|
285
|
+
@disasmlog = Zlib::GzipWriter.new(File.open(@disasmlog_filename, "wb"), nil, nil)
|
286
|
+
@disasmlog.puts "#{RUBY_ENGINE}-#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"
|
287
|
+
@disasmlog.puts "# " + `rails --version`.chomp
|
288
|
+
@disasmlog.puts
|
289
|
+
end
|
290
|
+
|
291
|
+
def self.finalize_archive
|
292
|
+
@disasmlog.close unless @disasmlog.nil?
|
293
|
+
end
|
294
|
+
|
295
|
+
def self.add_to_archive(data)
|
296
|
+
if @disasmlog.nil?
|
297
|
+
prepare_archive
|
298
|
+
end
|
299
|
+
@disasmlog.write(data)
|
300
|
+
end
|
301
|
+
|
302
|
+
|
303
|
+
def self.format_method(m, kind, with_disasm=true)
|
304
|
+
return "" unless ((m.is_a? Method ) || (m.is_a? UnboundMethod))
|
305
|
+
|
306
|
+
puts " #{kind}_method #{quote(safe_name(m))}" if $options[:verbose]
|
307
|
+
|
308
|
+
formatted = "#{kind}_method #{quote(safe_name(m))} #{m.parameters.to_s}\n"
|
309
|
+
|
310
|
+
if with_disasm
|
311
|
+
insns = RubyVM::InstructionSequence.disassemble(m)
|
312
|
+
formatted += ( (insns.nil? || insns.empty?) ?
|
313
|
+
"== disasm\n== end disasm\n" :
|
314
|
+
"#{insns}== end disasm\n"
|
315
|
+
)
|
316
|
+
end
|
317
|
+
|
318
|
+
formatted
|
319
|
+
end
|
320
|
+
|
321
|
+
def self.format_variable(v_symbol, v, kind)
|
322
|
+
puts " #{quote(kind)} variable #{quote(v_symbol)}" if $options[:verbose]
|
323
|
+
|
324
|
+
"#{kind}_variable %s %s%s\n" %
|
325
|
+
[quote(v.class), quote(v_symbol), ( good_type?(v) ? " = #{safe_inspect(v)}" : "")]
|
326
|
+
end
|
327
|
+
|
328
|
+
def self.format_constant(c_symbol, c)
|
329
|
+
puts " constant #{quote(c_symbol)}" if $options[:verbose]
|
330
|
+
|
331
|
+
"constant %s %s%s\n" %
|
332
|
+
[quote(c.class), quote(c_symbol), ( good_type?(c) ? " = #{safe_inspect(c)}" : "")]
|
333
|
+
end
|
334
|
+
|
335
|
+
|
336
|
+
##############################################################################
|
337
|
+
# Archiving Headers
|
338
|
+
def self.class_header(c)
|
339
|
+
return "" unless c.is_a? Class
|
340
|
+
|
341
|
+
puts " class header" if $options[:verbose]
|
342
|
+
|
343
|
+
case
|
344
|
+
when c.superclass.nil? # this should only happen for BasicObject
|
345
|
+
return ""
|
346
|
+
when c.superclass.name.nil? # in case the parent is anonymous
|
347
|
+
name = c.superclass.to_s.dump
|
348
|
+
else
|
349
|
+
name = c.superclass.name.dump
|
350
|
+
end
|
351
|
+
|
352
|
+
"superclass #{name}\n"
|
353
|
+
end
|
354
|
+
|
355
|
+
def self.module_header(m)
|
356
|
+
return "" unless m.is_a? Module
|
357
|
+
|
358
|
+
puts " module header" if $options[:verbose]
|
359
|
+
|
360
|
+
( m.included_modules.count > 0 ?
|
361
|
+
m.included_modules.map {|m| "include #{m.inspect.dump}\n" }.join :
|
362
|
+
""
|
363
|
+
) +
|
364
|
+
( m.singleton_class.included_modules.count > 0 ?
|
365
|
+
m.singleton_class.included_modules.map {|m| "extend #{m.inspect.dump}\n" }.join :
|
366
|
+
""
|
367
|
+
)
|
368
|
+
end
|
369
|
+
|
370
|
+
|
371
|
+
##############################################################################
|
372
|
+
# Archiving Contents
|
373
|
+
def self.module_contents(m, with_disasm=true)
|
374
|
+
return "" unless m.is_a? Module
|
375
|
+
|
376
|
+
puts " module contents" if $options[:verbose]
|
377
|
+
|
378
|
+
formatted_contents = ""
|
379
|
+
|
380
|
+
m.constants($options[:include_inherited]).each do |c_symbol|
|
381
|
+
begin
|
382
|
+
c = m.const_get(c_symbol) if m.const_defined? c_symbol
|
383
|
+
formatted_contents += format_constant(c_symbol, c)
|
384
|
+
rescue Exception => e
|
385
|
+
log_error "Error archiving constant #{c_symbol.to_s.dump}: #{e.message}"
|
386
|
+
formatted_contents += format_constant(c_symbol, :veracode_nil)
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
m.class_variables.each do |v_symbol|
|
391
|
+
begin
|
392
|
+
v = m.class_variable_get(v_symbol)
|
393
|
+
formatted_contents += format_variable(v_symbol, v, "class")
|
394
|
+
rescue Exception => e
|
395
|
+
log_error "Error archiving class variable #{v_symbol.to_s.dump}: #{e.message}"
|
396
|
+
formatted_contents += format_variable(v_symbol, :veracode_nil, "class")
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
if m.respond_to?(:global_variables)
|
401
|
+
m.global_variables.each do |v_symbol|
|
402
|
+
begin
|
403
|
+
v = eval(v_symbol.to_s)
|
404
|
+
formatted_contents += format_variable(v_symbol, v, "global")
|
405
|
+
rescue Exception => e
|
406
|
+
log_error "Error archiving global variable #{v_symbol.to_s.dump}: #{e.message}"
|
407
|
+
formatted_contents += format_variable(v_symbol, :veracode_nil, "global")
|
408
|
+
end
|
409
|
+
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
%w[ public protected private ].each {|p|
|
414
|
+
get_methods = (p + "_instance_methods").to_sym
|
415
|
+
if m.respond_to?(get_methods) && m.send(get_methods, $options[:include_inherited]).count > 0
|
416
|
+
m.send(get_methods, $options[:include_inherited]).each do |m_symbol|
|
417
|
+
begin
|
418
|
+
method = m.instance_method(m_symbol)
|
419
|
+
formatted_contents += format_method(method, "#{p.to_s}_instance", with_disasm)
|
420
|
+
rescue Exception => e
|
421
|
+
log_error "Error archiving #{p.to_s} instance method #{m_symbol.to_s.dump}: #{e.message}"
|
422
|
+
end
|
423
|
+
end
|
424
|
+
end
|
425
|
+
}
|
426
|
+
|
427
|
+
formatted_contents
|
428
|
+
end
|
429
|
+
|
430
|
+
def self.object_contents(o, with_disasm=true)
|
431
|
+
return "" unless o.is_a? Object
|
432
|
+
|
433
|
+
puts " object contents" if $options[:verbose]
|
434
|
+
|
435
|
+
formatted_contents = ""
|
436
|
+
|
437
|
+
if o.respond_to?(:instance_variables) && o.instance_variables.count > 0
|
438
|
+
o.instance_variables.each do |v_symbol|
|
439
|
+
begin
|
440
|
+
v = o.instance_variable_get(v_symbol)
|
441
|
+
formatted_contents += format_variable(v_symbol, v, "instance")
|
442
|
+
rescue Exception => e
|
443
|
+
log_error "Error archiving instance variable #{v_symbol.to_s.dump}: #{e.message}"
|
444
|
+
formatted_contents += format_variable(v_symbol, :veracode_nil, "instance")
|
445
|
+
end
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
if o.respond_to?(:singleton_methods) && o.singleton_methods($options[:include_inherited]).count > 0
|
450
|
+
o.singleton_methods($options[:include_inherited]).each do |m_symbol|
|
451
|
+
begin
|
452
|
+
m = o.method(m_symbol)
|
453
|
+
formatted_contents += format_method(m, "singleton", with_disasm)
|
454
|
+
rescue Exception => e
|
455
|
+
log_error "Error archiving singleton method #{m_symbol.to_s.dump}: #{e.message}"
|
456
|
+
end
|
457
|
+
end
|
458
|
+
end
|
459
|
+
|
460
|
+
formatted_contents
|
461
|
+
end
|
462
|
+
|
463
|
+
|
464
|
+
##############################################################################
|
465
|
+
# Archiving Objects
|
466
|
+
def self.archive(objects, with_disasm=true)
|
467
|
+
|
468
|
+
objects = objects - [Veracode]
|
469
|
+
|
470
|
+
if $options[:verbose]
|
471
|
+
puts "Archiving #{objects.count.to_s} objects" + (with_disasm ? " with disassembly" : "")
|
472
|
+
puts
|
473
|
+
end
|
474
|
+
|
475
|
+
objects.sort_by {|o| safe_name(o) }.each do |o|
|
476
|
+
|
477
|
+
puts "archiving #{o.class.to_s.downcase} #{quote(safe_name(o))}" if $options[:verbose]
|
478
|
+
|
479
|
+
add_to_archive "#{o.class.to_s.downcase} #{quote(safe_name(o))}\n" +
|
480
|
+
|
481
|
+
( o.is_a?(Class) ? class_header(o) : "") + # superclass
|
482
|
+
( o.is_a?(Module) ? module_header(o) : "") + # included modules
|
483
|
+
|
484
|
+
( o.is_a?(Object) ? object_contents(o, with_disasm) : "") +
|
485
|
+
( o.is_a?(Module) ? module_contents(o, with_disasm) : "") +
|
486
|
+
|
487
|
+
"end#{o.class.to_s.downcase}\n" +
|
488
|
+
"\n"
|
489
|
+
end
|
490
|
+
|
491
|
+
end
|
492
|
+
|
493
|
+
|
494
|
+
def self.compile_erb_templates
|
495
|
+
|
496
|
+
# Rails 3 has wrapped Erubis to handle block helpers in ERB templates
|
497
|
+
# a little differently, e.g.:
|
498
|
+
# <%= form_for ... do %>
|
499
|
+
# vs the normal ERB:
|
500
|
+
# <% form_for ... do %>
|
501
|
+
#
|
502
|
+
# This means if Rails 3 erb templates are compiled with ERB or Erubis
|
503
|
+
# the resulting ruby source code will contain syntax errors.
|
504
|
+
# To avoid this, use the ActionView templates and handlers
|
505
|
+
|
506
|
+
view_paths = []
|
507
|
+
view_paths += ActionController::Base.view_paths.to_a.map(&:to_s)
|
508
|
+
view_paths |= [File.expand_path("app/views")]
|
509
|
+
|
510
|
+
puts "Looking for erb templates in #{view_paths.join(", ")}" if $options[:verbose]
|
511
|
+
|
512
|
+
templates = view_paths.map { |vp|
|
513
|
+
Dir[File.join(vp, "**", "*.erb")]
|
514
|
+
}.flatten
|
515
|
+
|
516
|
+
return unless templates.count > 0
|
517
|
+
|
518
|
+
puts "Found #{templates.count} erb templates" if $options[:verbose]
|
519
|
+
|
520
|
+
templates.each {|template|
|
521
|
+
|
522
|
+
puts "Compiling template #{template}" if $options[:verbose]
|
523
|
+
|
524
|
+
begin
|
525
|
+
|
526
|
+
t = ActionView::Template.new(
|
527
|
+
File.read(template),
|
528
|
+
template,
|
529
|
+
ActionView::Template::Handlers::ERB,
|
530
|
+
:virtual_path => template
|
531
|
+
)
|
532
|
+
|
533
|
+
case t.method(:compile).arity
|
534
|
+
when 2 # Rails 3.1.0+
|
535
|
+
t.send(:compile, ActionView::Base.new, ActionView::CompiledTemplates)
|
536
|
+
when 3
|
537
|
+
t.send(:compile, {}, ActionView::Base.new, ActionView::CompiledTemplates)
|
538
|
+
end
|
539
|
+
|
540
|
+
rescue Exception => e
|
541
|
+
puts "Unable to compile template #{template}"
|
542
|
+
log_error "Unable to compile template #{template} (#{e.message})"
|
543
|
+
end
|
544
|
+
|
545
|
+
}
|
546
|
+
|
547
|
+
puts "Compiled templates: " + ActionView::CompiledTemplates.instance_methods.count.to_s if $options[:verbose]
|
548
|
+
|
549
|
+
end
|
550
|
+
|
551
|
+
def self.compile_haml_templates
|
552
|
+
|
553
|
+
view_paths = []
|
554
|
+
view_paths += ActionController::Base.view_paths.to_a.map(&:to_s)
|
555
|
+
view_paths |= [File.expand_path("app/views")]
|
556
|
+
|
557
|
+
puts "Looking for haml templates in #{view_paths.join(", ")}" if $options[:verbose]
|
558
|
+
|
559
|
+
templates = view_paths.map {|vp|
|
560
|
+
Dir[File.join(vp, "**", "*.haml")]
|
561
|
+
}.flatten
|
562
|
+
|
563
|
+
return unless templates.count > 0
|
564
|
+
|
565
|
+
begin
|
566
|
+
require 'action_view'
|
567
|
+
require 'haml'
|
568
|
+
require 'haml/template/plugin'
|
569
|
+
rescue Exception => e
|
570
|
+
log_error "Unable to satisfy haml dependencies (#{e.message})"
|
571
|
+
return
|
572
|
+
end
|
573
|
+
|
574
|
+
puts "Found #{templates.count} haml templates" if $options[:verbose]
|
575
|
+
|
576
|
+
templates.each {|template|
|
577
|
+
|
578
|
+
puts "Compiling template #{template}" if $options[:verbose]
|
579
|
+
|
580
|
+
begin
|
581
|
+
|
582
|
+
t = ActionView::Template.new(
|
583
|
+
File.read(template),
|
584
|
+
template,
|
585
|
+
Haml::Plugin,
|
586
|
+
:virtual_path => template
|
587
|
+
)
|
588
|
+
|
589
|
+
case t.method(:compile).arity
|
590
|
+
when 2 # Rails 3.1.0+
|
591
|
+
t.send(:compile, ActionView::Base.new, ActionView::CompiledTemplates)
|
592
|
+
when 3
|
593
|
+
t.send(:compile, {}, ActionView::Base.new, ActionView::CompiledTemplates)
|
594
|
+
end
|
595
|
+
|
596
|
+
rescue Exception => e
|
597
|
+
puts "Unable to compile template #{template}"
|
598
|
+
log_error "Unable to compile template #{template} (#{e.message})"
|
599
|
+
end
|
600
|
+
|
601
|
+
}
|
602
|
+
|
603
|
+
puts "Compiled templates: " + ActionView::CompiledTemplates.instance_methods.count.to_s if $options[:verbose]
|
604
|
+
|
605
|
+
end
|
606
|
+
|
607
|
+
|
608
|
+
|
609
|
+
|
610
|
+
################################################################################
|
611
|
+
# Subcommands
|
612
|
+
def self.prepare
|
613
|
+
|
614
|
+
init
|
615
|
+
|
616
|
+
puts "Preparing Ruby on Rails application #{APP_NAME.dump} for Veracode upload"
|
617
|
+
puts "Source code will be included in the archive" if $options[:archive_source]
|
618
|
+
|
619
|
+
if $options[:verbose]
|
620
|
+
puts Dir.pwd.to_s.dump
|
621
|
+
puts
|
622
|
+
end
|
623
|
+
|
624
|
+
if $options[:disasm]
|
625
|
+
rbfiles = File.join("**", "*.rb")
|
626
|
+
Dir[rbfiles].each do |f|
|
627
|
+
puts RubyVM::InstructionSequence.compile_file(f).disasm
|
628
|
+
puts
|
629
|
+
end
|
630
|
+
exit
|
631
|
+
end
|
632
|
+
|
633
|
+
prepare_archive
|
634
|
+
|
635
|
+
################################################################
|
636
|
+
## phase 1 - Create baseline
|
637
|
+
self.baseline
|
638
|
+
|
639
|
+
puts "Phase 1 - Initial State" if $options[:verbose]
|
640
|
+
self.stats if $options[:verbose]
|
641
|
+
|
642
|
+
if $options[:phase1]
|
643
|
+
puts "Processing and disassembling Ruby standard classes and modules"
|
644
|
+
archive(@modules)
|
645
|
+
end
|
646
|
+
## /phase 1 - Create baseline
|
647
|
+
################################################################
|
648
|
+
|
649
|
+
|
650
|
+
|
651
|
+
################################################################
|
652
|
+
## phase 2 - Require rails
|
653
|
+
|
654
|
+
puts "Phase 2 - Load Rails" if $options[:verbose]
|
655
|
+
begin
|
656
|
+
require "rails"
|
657
|
+
rescue Exception => e
|
658
|
+
puts "Unable to require rails: #{e.message}"
|
659
|
+
log_error "Unable to require rails: #{e.message}"
|
660
|
+
exit
|
661
|
+
else
|
662
|
+
puts "Required rails" if $options[:verbose]
|
663
|
+
end
|
664
|
+
|
665
|
+
self.update
|
666
|
+
|
667
|
+
self.stats if $options[:verbose]
|
668
|
+
|
669
|
+
if $options[:phase2]
|
670
|
+
puts "Processing and disassembling Rails classes and modules"
|
671
|
+
archive(@modules)
|
672
|
+
end
|
673
|
+
|
674
|
+
self.rebaseline
|
675
|
+
## /phase 2 - Require rails
|
676
|
+
################################################################
|
677
|
+
|
678
|
+
|
679
|
+
|
680
|
+
################################################################
|
681
|
+
# phase 3 - require app
|
682
|
+
|
683
|
+
puts "Phase 3 - Imitate Rails" if $options[:verbose]
|
684
|
+
|
685
|
+
## Imitate script/rails
|
686
|
+
# APP_PATH = File.expand_path('config/application')
|
687
|
+
# APP_PATH is already set in bin/veracode
|
688
|
+
#require File.expand_path('../../config/boot', __FILE__)
|
689
|
+
glob_require "config/boot.rb"
|
690
|
+
#require 'rails/commands'
|
691
|
+
# this will trigger the console to be launched
|
692
|
+
# ARGV.clear
|
693
|
+
# ARGV << 'console'
|
694
|
+
# ARGV << '--sandbox'
|
695
|
+
# require 'rails/commands'
|
696
|
+
|
697
|
+
## Imitate rails/commands when console
|
698
|
+
glob_require 'rails/commands/console'
|
699
|
+
# require APP_PATH # => config/application.rb
|
700
|
+
|
701
|
+
glob_require "config/application.rb"
|
702
|
+
|
703
|
+
Rails.application.require_environment! unless $options[:jruby]
|
704
|
+
# Following line will actually kick off IRB
|
705
|
+
# Rails::Console.start(Rails.application)
|
706
|
+
|
707
|
+
# Imitate Rails::Console.initialize_console
|
708
|
+
# require "pp"
|
709
|
+
glob_require "rails/console/app"
|
710
|
+
glob_require "rails/console/helpers"
|
711
|
+
|
712
|
+
glob_require "app/models/**/*.rb"
|
713
|
+
glob_require "app/helpers/**/*.rb"
|
714
|
+
glob_require "app/controllers/application_controller.rb"
|
715
|
+
glob_require "app/controllers/**/*.rb"
|
716
|
+
|
717
|
+
compile_erb_templates
|
718
|
+
compile_haml_templates
|
719
|
+
|
720
|
+
self.update
|
721
|
+
self.stats if $options[:verbose]
|
722
|
+
|
723
|
+
if $options[:phase3]
|
724
|
+
puts "Processing and disassembling #{APP_NAME} classes and modules"
|
725
|
+
archive(@baseline_modules, false)
|
726
|
+
archive(@modules - @baseline_modules, true)
|
727
|
+
end
|
728
|
+
|
729
|
+
## /phase 3 - require app
|
730
|
+
################################################################
|
731
|
+
|
732
|
+
finalize_archive
|
733
|
+
|
734
|
+
pack_manifest
|
735
|
+
cleanup
|
736
|
+
|
737
|
+
end # self.prepare
|
738
|
+
|
739
|
+
end
|
metadata
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: veracode
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0.alpha
|
5
|
+
prerelease: 6
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Veracode
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-05-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rubyzip
|
16
|
+
requirement: &70257511683960 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70257511683960
|
25
|
+
description: Prepares your Ruby on Rails app for submission to Veracode.
|
26
|
+
email: devcontact@veracode.com
|
27
|
+
executables:
|
28
|
+
- veracode
|
29
|
+
extensions: []
|
30
|
+
extra_rdoc_files: []
|
31
|
+
files:
|
32
|
+
- bin/veracode
|
33
|
+
- lib/veracode.rb
|
34
|
+
- lib/veracode/version.rb
|
35
|
+
homepage: http://veracode.com/
|
36
|
+
licenses: []
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options: []
|
39
|
+
require_paths:
|
40
|
+
- lib
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ~>
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 1.9.3.0
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
none: false
|
49
|
+
requirements:
|
50
|
+
- - ! '>'
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 1.3.1
|
53
|
+
requirements: []
|
54
|
+
rubyforge_project:
|
55
|
+
rubygems_version: 1.8.10
|
56
|
+
signing_key:
|
57
|
+
specification_version: 3
|
58
|
+
summary: Command line tool for preparing your Ruby on Rails app for submission to
|
59
|
+
Veracode
|
60
|
+
test_files: []
|