stratagem 0.2.3 → 0.2.4

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.
Files changed (65) hide show
  1. data/Manifest +16 -6
  2. data/Rakefile +8 -1
  3. data/lib/generators/stratagem/install/install_base.rb +13 -3
  4. data/lib/generators/stratagem/install/install_generator.rb +1 -1
  5. data/lib/stratagem.rb +42 -18
  6. data/lib/stratagem/authentication.rb +2 -5
  7. data/lib/stratagem/auto_mock.rb +1 -0
  8. data/lib/stratagem/auto_mock/aquifer.rb +49 -26
  9. data/lib/stratagem/auto_mock/factory.rb +1 -6
  10. data/lib/stratagem/auto_mock/user_loader.rb +38 -0
  11. data/lib/stratagem/client.rb +15 -4
  12. data/lib/stratagem/configuration/auth_auth.rb +19 -0
  13. data/lib/stratagem/configuration/core.rb +20 -0
  14. data/lib/stratagem/crawler/authentication.rb +17 -12
  15. data/lib/stratagem/crawler/authentication/automated.rb +40 -0
  16. data/lib/stratagem/crawler/authentication/base.rb +140 -0
  17. data/lib/stratagem/crawler/authentication/configured.rb +27 -0
  18. data/lib/stratagem/crawler/parameter_resolver.rb +12 -8
  19. data/lib/stratagem/crawler/route_invoker.rb +10 -13
  20. data/lib/stratagem/crawler/session.rb +14 -2
  21. data/lib/stratagem/crawler/site_model.rb +4 -173
  22. data/lib/stratagem/crawler/site_model/edge.rb +20 -0
  23. data/lib/stratagem/crawler/site_model/page.rb +121 -0
  24. data/lib/stratagem/crawler/site_model/page_set.rb +58 -0
  25. data/lib/stratagem/instrumentation/models.rb +3 -14
  26. data/lib/stratagem/instrumentation/models/annotations.rb +39 -5
  27. data/lib/stratagem/instrumentation/models/authentication.rb +0 -1
  28. data/lib/stratagem/instrumentation/models/authentication/authlogic/detect.rb +1 -0
  29. data/lib/stratagem/instrumentation/models/authentication/devise/detect.rb +1 -1
  30. data/lib/stratagem/instrumentation/models/authentication/devise/instrumentation.rb +0 -4
  31. data/lib/stratagem/instrumentation/models/metadata.rb +23 -1
  32. data/lib/stratagem/instrumentation/models/persistence.rb +3 -4
  33. data/lib/stratagem/instrumentation/models/persistence/active_record/metadata.rb +2 -2
  34. data/lib/stratagem/interface/browser.rb +9 -3
  35. data/lib/stratagem/interface/public/javascripts/stratagem.js +14 -12
  36. data/lib/stratagem/interface/views/index.haml +3 -3
  37. data/lib/stratagem/logger.rb +28 -2
  38. data/lib/stratagem/model.rb +6 -0
  39. data/lib/stratagem/model/application.rb +21 -134
  40. data/lib/stratagem/model/components/base.rb +1 -4
  41. data/lib/stratagem/model/components/controller.rb +1 -2
  42. data/lib/stratagem/model/components/model.rb +15 -15
  43. data/lib/stratagem/model/components/route.rb +3 -2
  44. data/lib/stratagem/model/components/view.rb +0 -1
  45. data/lib/stratagem/model/containers/base.rb +60 -0
  46. data/lib/stratagem/model/containers/gem.rb +25 -0
  47. data/lib/stratagem/model/containers/plugin.rb +11 -0
  48. data/lib/stratagem/model/containers/route.rb +19 -0
  49. data/lib/stratagem/model/parse_util.rb +3 -3
  50. data/lib/stratagem/model_builder.rb +1 -4
  51. data/lib/stratagem/rack_hack.rb +15 -0
  52. data/lib/stratagem/site_crawler.rb +5 -4
  53. data/lib/stratagem/snapshot.rb +5 -7
  54. data/spec/stratagem/configuration_spec.rb +32 -0
  55. data/stratagem.gemspec +5 -8
  56. data/templates/install/environments/stratagem.rb.erb +31 -2
  57. data/templates/install/script/stratagem +16 -0
  58. data/templates/install/tasks/stratagem.rake +2 -2
  59. metadata +36 -65
  60. data/bin/stratagem +0 -58
  61. data/lib/stratagem/scan.rb +0 -19
  62. data/lib/stratagem/scan/checks/email_address.rb +0 -15
  63. data/lib/stratagem/scan/checks/error_pages.rb +0 -25
  64. data/lib/stratagem/scan/result.rb +0 -45
  65. data/lib/stratagem/scanner.rb +0 -32
data/Manifest CHANGED
@@ -1,7 +1,6 @@
1
1
  LICENSE
2
2
  Manifest
3
3
  Rakefile
4
- bin/stratagem
5
4
  generators/stratagem/stratagem_generator.rb
6
5
  init.rb
7
6
  lib/bootstrap.rb
@@ -13,6 +12,7 @@ lib/stratagem/authentication.rb
13
12
  lib/stratagem/auto_mock.rb
14
13
  lib/stratagem/auto_mock/aquifer.rb
15
14
  lib/stratagem/auto_mock/factory.rb
15
+ lib/stratagem/auto_mock/user_loader.rb
16
16
  lib/stratagem/auto_mock/value_generator.rb
17
17
  lib/stratagem/blocker.rb
18
18
  lib/stratagem/client.rb
@@ -21,14 +21,22 @@ lib/stratagem/commands.rb
21
21
  lib/stratagem/commands/analyze.rb
22
22
  lib/stratagem/commands/base.rb
23
23
  lib/stratagem/commands/devel_mock.rb
24
+ lib/stratagem/configuration/auth_auth.rb
25
+ lib/stratagem/configuration/core.rb
24
26
  lib/stratagem/crawler.rb
25
27
  lib/stratagem/crawler/authentication.rb
28
+ lib/stratagem/crawler/authentication/automated.rb
29
+ lib/stratagem/crawler/authentication/base.rb
30
+ lib/stratagem/crawler/authentication/configured.rb
26
31
  lib/stratagem/crawler/form.rb
27
32
  lib/stratagem/crawler/html_utils.rb
28
33
  lib/stratagem/crawler/parameter_resolver.rb
29
34
  lib/stratagem/crawler/route_invoker.rb
30
35
  lib/stratagem/crawler/session.rb
31
36
  lib/stratagem/crawler/site_model.rb
37
+ lib/stratagem/crawler/site_model/edge.rb
38
+ lib/stratagem/crawler/site_model/page.rb
39
+ lib/stratagem/crawler/site_model/page_set.rb
32
40
  lib/stratagem/crawler/trace_utils.rb
33
41
  lib/stratagem/extensions.rb
34
42
  lib/stratagem/extensions/class.rb
@@ -102,16 +110,18 @@ lib/stratagem/model/components/reference.rb
102
110
  lib/stratagem/model/components/route.rb
103
111
  lib/stratagem/model/components/static_file.rb
104
112
  lib/stratagem/model/components/view.rb
113
+ lib/stratagem/model/containers/base.rb
114
+ lib/stratagem/model/containers/gem.rb
115
+ lib/stratagem/model/containers/plugin.rb
116
+ lib/stratagem/model/containers/route.rb
105
117
  lib/stratagem/model/parse_util.rb
106
118
  lib/stratagem/model_builder.rb
119
+ lib/stratagem/rack_hack.rb
107
120
  lib/stratagem/recipes/deploy.rb
108
- lib/stratagem/scan.rb
109
121
  lib/stratagem/scan/checks/capistrano/secure_deploy.rb
110
- lib/stratagem/scan/checks/email_address.rb
111
- lib/stratagem/scan/checks/error_pages.rb
112
- lib/stratagem/scan/result.rb
113
- lib/stratagem/scanner.rb
114
122
  lib/stratagem/site_crawler.rb
115
123
  lib/stratagem/snapshot.rb
124
+ spec/stratagem/configuration_spec.rb
116
125
  templates/install/environments/stratagem.rb.erb
126
+ templates/install/script/stratagem
117
127
  templates/install/tasks/stratagem.rake
data/Rakefile CHANGED
@@ -1,8 +1,14 @@
1
1
  require 'rubygems'
2
2
  require 'rake'
3
3
  require 'echoe'
4
+ require "rspec"
5
+ require "rspec/core/rake_task"
4
6
 
5
- Echoe.new('stratagem', '0.2.3') do |p|
7
+ Rspec::Core::RakeTask.new(:spec) do |spec|
8
+ spec.pattern = "spec/**/*_spec.rb"
9
+ end
10
+
11
+ Echoe.new('stratagem', '0.2.4') do |p|
6
12
  p.description = "Intuitive security analysis for your Rails applications"
7
13
  p.url = "http://www.stratagemapp.com"
8
14
  p.author = "Charles Grimes"
@@ -15,3 +21,4 @@ Echoe.new('stratagem', '0.2.3') do |p|
15
21
  end
16
22
 
17
23
  Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
24
+
@@ -2,20 +2,30 @@ module Stratagem
2
2
  module Generators
3
3
  module InstallBase
4
4
  def create_all(m=self)
5
+ create_scripts(m)
5
6
  create_config(m)
6
7
  create_tasks(m)
7
8
  create_database(m)
8
9
  end
9
10
 
10
- def create_config(m = self)
11
+ def create_scripts(m)
12
+ m.template('script/stratagem', 'script/stratagem', options)
13
+ begin
14
+ chmod 'script/stratagem', 0755
15
+ rescue
16
+ puts "ERROR: #{$!.message}"
17
+ end
18
+ end
19
+
20
+ def create_config(m)
11
21
  m.template 'environments/stratagem.rb.erb', 'config/environments/stratagem.rb'
12
22
  end
13
23
 
14
- def create_tasks(m = self)
24
+ def create_tasks(m)
15
25
  m.template 'tasks/stratagem.rake', 'lib/tasks/stratagem.rake'
16
26
  end
17
27
 
18
- def create_database(m = self)
28
+ def create_database(m)
19
29
  append_yml(m, 'mongoid.yml', 'database.yml', 'workling.yml')
20
30
  end
21
31
 
@@ -5,7 +5,7 @@ module Stratagem
5
5
  include Stratagem::Generators::InstallBase
6
6
 
7
7
  def generate
8
- create_all
8
+ create_all(self)
9
9
  end
10
10
 
11
11
  def self.gem_root
@@ -1,3 +1,6 @@
1
+ require 'stratagem/configuration/core'
2
+ require 'stratagem/configuration/auth_auth'
3
+
1
4
  class StratagemError < RuntimeError
2
5
  attr_accessor :target
3
6
 
@@ -9,10 +12,25 @@ end
9
12
 
10
13
  module Stratagem
11
14
  class << self
15
+ def configure(&block)
16
+ @@configuration = Configuration::Core.new
17
+ block.call(@@configuration) if block
18
+ @@configuration
19
+ end
20
+
21
+ def configuration
22
+ @@configuration
23
+ end
24
+
25
+ def prescan(&block)
26
+ @@prescan = block if block
27
+ end
28
+
12
29
  def load_dependencies
13
30
  require 'haml'
14
31
  require 'launchy'
15
32
  require 'redparse'
33
+ require 'stratagem/rack_hack'
16
34
  require 'stratagem/blocker'
17
35
  require 'stratagem/logger'
18
36
  require 'stratagem/extensions'
@@ -25,8 +43,6 @@ module Stratagem
25
43
  require 'stratagem/client'
26
44
  require 'stratagem/command'
27
45
  require 'stratagem/model_builder'
28
- require 'stratagem/scanner'
29
- require 'stratagem/scan'
30
46
  require 'stratagem/crawler'
31
47
  require 'stratagem/site_crawler'
32
48
  require 'stratagem/snapshot'
@@ -36,25 +52,25 @@ module Stratagem
36
52
 
37
53
  def init
38
54
  load_dependencies
39
-
55
+
56
+ @@prescan = nil
40
57
  @@blocker = Blocker.new
41
58
  @@running = false
42
59
  @@session_id = Time.now.to_f.to_s # the interface uses this to determine which instance of the client it's talking to
43
60
  end
44
61
 
45
62
  def ssl?
46
- true
63
+ !local?
47
64
  end
48
65
 
49
66
  def domain
50
- 'stratagemapp.com'
51
- end
52
-
53
- def mocking?
54
- true
67
+ if local?
68
+ 'localhost:3000'
69
+ else
70
+ 'stratagemapp.com'
71
+ end
55
72
  end
56
73
 
57
-
58
74
  def rails_version
59
75
  @@rails_version ||= begin
60
76
  rails_version = Rails.version.split('.').map {|v| v.size > 1 ? 9 : v.to_i }
@@ -80,7 +96,6 @@ module Stratagem
80
96
  Stratagem::Logger.instance
81
97
  end
82
98
 
83
- # register an error that occurred during the lifecycle of the scanner
84
99
  def error(error)
85
100
  errors << error
86
101
  end
@@ -94,6 +109,7 @@ module Stratagem
94
109
  end
95
110
 
96
111
  def complete
112
+ Stratagem.logger.phase('complete')
97
113
  @@blocker.notify
98
114
  end
99
115
 
@@ -102,27 +118,35 @@ module Stratagem
102
118
  @@running = true
103
119
  Thread.new {
104
120
  begin
105
- # RubyProf.start
121
+ if (configuration.use_transactional_crawling)
122
+ ActiveRecord::Base.connection.increment_open_transactions
123
+ ActiveRecord::Base.connection.transaction_joinable = false
124
+ ActiveRecord::Base.connection.begin_db_transaction
125
+ end
106
126
 
127
+ prescan.call unless prescan.nil?
107
128
  authentication = Stratagem::Authentication.instance
108
129
  snapshot = Stratagem::Snapshot.create(authentication.project)
109
130
  Stratagem::Client.new(authentication).send(snapshot)
110
-
111
- # result = RubyProf.stop
112
- #
113
- # # Print a flat profile to text
114
- # printer = RubyProf::FlatPrinter.new(result)
115
- # printer.print(STDOUT, 0)
116
131
  rescue Exception
117
132
  puts $!.message
118
133
  puts $!.backtrace
119
134
  ensure
135
+ if (configuration.use_transactional_crawling)
136
+ ActiveRecord::Base.connection.decrement_open_transactions
137
+ ActiveRecord::Base.connection.rollback_db_transaction
138
+ end
139
+
120
140
  complete
121
141
  end
122
142
  }
123
143
  end
124
144
  end
125
145
 
146
+
147
+ def local?
148
+ ENV['local'] && ENV['local'] == 'true'
149
+ end
126
150
  end
127
151
 
128
152
  end
@@ -9,9 +9,8 @@ module Stratagem
9
9
 
10
10
  attr_reader :token, :project
11
11
 
12
- def store_credentials(account, token, project)
12
+ def store_credentials(token, project)
13
13
  File.open(FILENAME, 'w') do |f|
14
- f.puts account
15
14
  f.puts token
16
15
  f.puts project
17
16
  end
@@ -27,9 +26,8 @@ module Stratagem
27
26
  end
28
27
 
29
28
  def base_url
30
- subdomain = credentials ? credentials[:account] : 'www'
31
29
  protocol = Stratagem.ssl? ? 'https' : 'http'
32
- "#{protocol}://#{subdomain}.#{Stratagem.domain}"
30
+ "#{protocol}://#{Stratagem.domain}"
33
31
  end
34
32
 
35
33
  def project_url
@@ -51,7 +49,6 @@ module Stratagem
51
49
  credentials = nil
52
50
  File.open(FILENAME) do |f|
53
51
  credentials = {
54
- :account => f.readline.strip,
55
52
  :token => f.readline.strip,
56
53
  :project => f.readline.strip
57
54
  }
@@ -1,6 +1,7 @@
1
1
  module Stratagem::AutoMock
2
2
  end
3
3
 
4
+ require 'stratagem/auto_mock/user_loader'
4
5
  require 'stratagem/auto_mock/value_generator'
5
6
  require 'stratagem/auto_mock/factory'
6
7
  require 'stratagem/auto_mock/aquifer'
@@ -4,6 +4,7 @@ module Stratagem::AutoMock
4
4
  class Aquifer
5
5
  include Singleton
6
6
  include Factory
7
+ include UserLoader
7
8
 
8
9
  attr_accessor :application
9
10
 
@@ -14,7 +15,7 @@ module Stratagem::AutoMock
14
15
  end
15
16
 
16
17
  def clear
17
- if (Stratagem.mocking?)
18
+ if (Stratagem.configuration.use_automatic_mocking)
18
19
  objects = self.repo.values.inject([]) {|memo,obj| memo += obj.compact }
19
20
  i = 0
20
21
  while (objects.size > 0 && ((i+=1) < objects.size))
@@ -28,7 +29,7 @@ module Stratagem::AutoMock
28
29
  instance.delete
29
30
  rescue
30
31
  puts "Unable to delete object: #{instance.class.name} - #{$!.message}"
31
- puts $!.backtrace
32
+ Stratagem.logger.error($!)
32
33
  end
33
34
  end
34
35
  !instance.frozen?
@@ -71,23 +72,19 @@ module Stratagem::AutoMock
71
72
  end
72
73
 
73
74
  def load_existing_object_ids(klass)
74
- if (Stratagem.mocking?)
75
- # handle polymorphic objects (class may actually be a subclass of the klass parameter)
76
- klass.existing_instance_ids.each do |existing_id|
77
- if (existing_id.kind_of?(Fixnum))
78
- begin
79
- instance = klass.find(existing_id)
80
- (pre_existing_object_ids[instance.class] ||= []) << existing_id
81
- rescue
82
- puts "ERROR: instance id #{existing_id} of #{klass.name} could not be loaded"
83
- end
84
- else
85
- # an instance was loaded because the model has no id field
75
+ # handle polymorphic objects (class may actually be a subclass of the klass parameter)
76
+ klass.existing_instance_ids.each do |existing_id|
77
+ if (existing_id.kind_of?(Fixnum))
78
+ begin
79
+ instance = klass.find(existing_id)
86
80
  (pre_existing_object_ids[instance.class] ||= []) << existing_id
81
+ rescue
82
+ puts "ERROR: instance id #{existing_id} of #{klass.name} could not be loaded - #{$!.message}"
87
83
  end
84
+ else
85
+ # an instance was loaded because the model has no id field
86
+ (pre_existing_object_ids[instance.class] ||= []) << existing_id
88
87
  end
89
- else
90
- pre_existing_object_ids[klass] = []
91
88
  end
92
89
  end
93
90
 
@@ -99,10 +96,33 @@ module Stratagem::AutoMock
99
96
  end
100
97
  end
101
98
 
99
+ def fill_by_configuration(credentials, model_count=nil)
100
+ objects_by_class = {}
101
+
102
+ log "Loading users for #{credentials.size} sets of credentials"
103
+ credentials.each do |user_credentials|
104
+ log "\t#{user_credentials.authentication_parameters.inspect}"
105
+ user = load_user_from_configuration(user_credentials)
106
+ if (user)
107
+ log "Loaded credentials for user #{user.id}: #{user.stratagem.mock_attributes.inspect}"
108
+ user.stratagem.related_objects.slice(0,5).each do |object|
109
+ (objects_by_class[object.class] ||= []) << object
110
+ end
111
+ else
112
+ Stratagem.logger.fatal "Could not locate user with credentials: #{user_credentials.authentication_parameters.inspect}"
113
+ end
114
+ end
115
+
116
+ log "Loaded #{objects_by_class.keys.size} object types: #{objects_by_class.keys.inspect}"
102
117
 
103
- def fill(model_count=nil)
104
- Stratagem.logger.phase "mocking_models"
118
+ objects_by_class.each do |klass, objects|
119
+ puts "filling aquifer - class #{klass.name} has #{objects.size} instances"
120
+ repo[klass.name] = objects
121
+ end
122
+ self
123
+ end
105
124
 
125
+ def fill_by_automock(model_count=nil)
106
126
  # load the ids of existing models for each class
107
127
  application.models.each do |meta_model|
108
128
  next unless meta_model.stratagem?
@@ -110,10 +130,8 @@ module Stratagem::AutoMock
110
130
  end
111
131
 
112
132
  # mock instances of all models
113
- if (Stratagem.mocking?)
114
- application.models.each do |meta_model|
115
- mock_model(meta_model.klass, model_count) if (meta_model.stratagem?)
116
- end
133
+ application.models.each do |meta_model|
134
+ mock_model(meta_model.klass, model_count) if (meta_model.stratagem?)
117
135
  end
118
136
 
119
137
  # determine the new ids for each model
@@ -123,12 +141,16 @@ module Stratagem::AutoMock
123
141
 
124
142
  known_mocked_instances = mocked(meta_model.klass)
125
143
  new_ids = load_instance_ids(meta_model) - (pre_existing_object_ids[meta_model.klass] || [])
144
+
145
+ # limit the number of objects that the system will interact with
146
+ new_ids = new_ids.slice(0,200)
126
147
  repo[meta_model.klass.name] = new_ids.map {|id|
127
148
  if (id.kind_of?(Fixnum))
149
+ puts "loading instance #{id} of #{meta_model.klass.name}"
128
150
  begin
129
151
  known_mocked_instances.find {|i| i.id == id } || meta_model.klass.find(id)
130
152
  rescue
131
- puts "ERROR: #{$!.message}"
153
+ puts "FILL ERROR: #{$!.message}"
132
154
  nil
133
155
  end
134
156
  else
@@ -160,6 +182,10 @@ module Stratagem::AutoMock
160
182
  end
161
183
  end
162
184
 
185
+ def repo
186
+ mocked
187
+ end
188
+
163
189
  protected
164
190
 
165
191
  def instance_call(instance, method, *args)
@@ -174,8 +200,5 @@ module Stratagem::AutoMock
174
200
  end
175
201
 
176
202
 
177
- def repo
178
- mocked
179
- end
180
203
  end
181
204
  end
@@ -48,12 +48,10 @@ module Stratagem::AutoMock
48
48
  end
49
49
  end
50
50
  rescue Exception, ActiveRecord::ActiveRecordError
51
- # puts $!.class.name
52
- # puts $!.message
53
- # puts $!.backtrace
54
51
  e = MockError.new("Unexpected error mocking model #{model.name} - #{$!.message}")
55
52
  puts e.message
56
53
  e.target = $!
54
+ Stratagem.logger.error(e)
57
55
  # raise e
58
56
  end
59
57
 
@@ -168,11 +166,8 @@ module Stratagem::AutoMock
168
166
  valid = false
169
167
  end
170
168
  puts "\tERROR: could not correct errors in model" unless valid
171
- # puts $!.backtrace unless valid
172
169
  end
173
170
 
174
- # puts "\t#{object.stratagem.mock_attributes.inspect}" if (valid)
175
-
176
171
  valid
177
172
  end
178
173