Skip to content

Commit

Permalink
Validations, associations and attendant specs
Browse files Browse the repository at this point in the history
MSP-12172

* Fix some errant docstrings declaring Array return types
* Change the name of status constants to be shorter
  • Loading branch information
trosen-r7 committed Feb 19, 2015
1 parent 1a43eaf commit 206cb4b
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 26 deletions.
21 changes: 14 additions & 7 deletions app/models/mdm/module/detail.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,44 +49,51 @@ class Mdm::Module::Detail < ActiveRecord::Base
# @!attribute [rw] actions
# Auxiliary actions to perform when this running this module.
#
# @return [Array<Mdm::Module::Action>]
# @return [ActiveRecord::Relation<Mdm::Module::Action>]
has_many :actions, :class_name => 'Mdm::Module::Action', :dependent => :destroy

# @!attribute [rw] archs
# Architectures supported by this module.
#
# @return [Array<Mdm::Module::Arch>]
# @return [ActiveRecord::Relation<Mdm::Module::Arch>]
has_many :archs, :class_name => 'Mdm::Module::Arch', :dependent => :destroy

# @!attribute [rw] authors
# Authors (and their emails) of this module. Usually includes the original discoverer who wrote the
# proof-of-concept and then the people that ported the proof-of-concept to metasploit-framework.
#
# @return [Array<Mdm::Module::Mixin>]
# @return [ActiveRecord::Relation<Mdm::Module::Mixin>]
has_many :authors, :class_name => 'Mdm::Module::Author', :dependent => :destroy

# @!attribute [rw] mixins
# Mixins used by this module.
#
# @return [Array<Mdm::Module::Mixin>]
# @return [ActiveRecord::Relation<Mdm::Module::Mixin>]
has_many :mixins, :class_name => 'Mdm::Module::Mixin', :dependent => :destroy

# @!attribute [rw] mixins
# Records of this module content having been attempted as part of Metasploit usage
# @return [ActiveRecord::Relation<MetasploitDataModels::ModuleRun>]
has_many :module_runs,
class_name: 'MetasploitDataModels::ModuleRun',
inverse_of: :module_detail

# @!attribute [rw] platforms
# Platforms supported by this module.
#
# @return [Array<Mdm::Module::Platform>]
# @return [ActiveRecord::Relation<Mdm::Module::Platform>]
has_many :platforms, :class_name => 'Mdm::Module::Platform', :dependent => :destroy

# @!attribute [rw] refs
# External references to the vulnerabilities this module exploits.
#
# @return [Array<Mdm::Module::Ref>]
# @return [ActiveRecord::Relation<Mdm::Module::Ref>]
has_many :refs, :class_name => 'Mdm::Module::Ref', :dependent => :destroy

# @!attribute [rw] targets
# Names of targets with different configurations that can be exploited by this module.
#
# @return [Array<Mdm::Module::Target>]
# @return [ActiveRecord::Relation<Mdm::Module::Target>]
has_many :targets, :class_name => 'Mdm::Module::Target', :dependent => :destroy

#
Expand Down
4 changes: 4 additions & 0 deletions app/models/mdm/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ class Mdm::User < ActiveRecord::Base
foreign_key: 'owner_id',
inverse_of: :owner

has_many :module_runs,
class_name: 'MetasploitDataModels::ModuleRun',
inverse_of: :user
has_many :tags,
class_name: 'Mdm::Tag',
inverse_of: :user


has_and_belongs_to_many :workspaces, :join_table => 'workspace_members', :uniq => true, :class_name => 'Mdm::Workspace'

#
Expand Down
48 changes: 39 additions & 9 deletions app/models/metasploit_data_models/module_run.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Holds the record of having launched piece of Metasploit content.
# Has associations to {Mdm::User} for audit purposes, and makes polymorphic associations to things like
# {MetasploitDataModels::ModuleRun} holds the record of having launched piece of Metasploit content.
# It has associations to {Mdm::User} for audit purposes, and makes polymorphic associations to things like
# {Mdm::Vuln} and {Mdm::Host} for flexible record keeping about activity attacking either specific vulns or just
# making mischief on specific remote targets w/out the context of a vuln or even a remote IP service.
class MetasploitDataModels::ModuleRun < ActiveRecord::Base
Expand All @@ -8,13 +8,13 @@ class MetasploitDataModels::ModuleRun < ActiveRecord::Base
#

# Marks the module as having successfully run
STATUS_EXPLOITED = 'exploited'
SUCCEED = 'succeeded'
# Marks the run as having not run successfully
STATUS_FAILED = 'failed'
FAIL = 'failed'
# Marks the module as having had a runtime error
STATUS_ERROR = 'error'
ERROR = 'error'
# {ModuleRun} objects will be validated against these statuses
VALID_STATUSES = [STATUS_EXPLOITED, STATUS_FAILED, STATUS_ERROR]
VALID_STATUSES = [SUCCEED, FAIL, ERROR]


#
Expand Down Expand Up @@ -56,7 +56,7 @@ class MetasploitDataModels::ModuleRun < ActiveRecord::Base

# @!attribute [rw] username
# The name of the user running this module
# @return [Datetime]
# @return [String]



Expand All @@ -65,14 +65,44 @@ class MetasploitDataModels::ModuleRun < ActiveRecord::Base
#


# A reference to the Metasploit content module in the DB cache
# @return [Mdm::Module::Detail]
belongs_to :module_detail,
class_name: 'Mdm::Module::Detail',
inverse_of: :module_runs

belongs_to :trackable, polymorphic: true

# The user that launched this module
# @return [Mdm::User]
belongs_to :user,
class_name: "Mdm::User",
foreign_key: "user_id",
class_name: 'Mdm::User',
foreign_key: 'user_id',
inverse_of: :module_runs



#
# Validations
#

validates :attempted_at,
presence: true

validate :module_information_is_present

validates :status,
inclusion: VALID_STATUSES


private

# Mark the object as invalid if there is no associated #module_name or {Mdm::ModuleDetail}
# @return [void]
def module_information_is_present
if module_name.blank? && module_detail.blank?
errors.add(:base, "One of module_name or module_detail_id must be set")
end
end

end
56 changes: 56 additions & 0 deletions spec/app/models/metasploit_data_models/module_run_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,63 @@

describe MetasploitDataModels::ModuleRun do

subject(:module_run){FactoryGirl.build(:module_run)}

context "associations" do
it { is_expected.to belong_to(:user).class_name('Mdm::User') }
it { is_expected.to belong_to(:trackable) }
end

context "validations" do
describe "attempted_at" do
before(:each){ module_run.attempted_at = nil }

it { is_expected.to_not be_valid }
end

describe "content information" do
context "when there is no module_name and no module_detail" do
before(:each) do
module_run.module_name = nil
module_run.module_detail = nil
end

it { is_expected.to_not be_valid }
end
end


describe "status" do
describe "invalidity" do
before(:each) do
module_run.status = "invalid nonsense"
end

it { expect(module_run).to_not be_valid}
end

describe "validity" do
context "when the module run succeeded" do
before(:each){ module_run.status = MetasploitDataModels::ModuleRun::SUCCEED}

it{ expect(module_run).to be_valid }
end

context "when the module run went normally but failed" do
before(:each){ module_run.status = MetasploitDataModels::ModuleRun::FAIL}

it{ expect(module_run).to be_valid }
end

context "when the module run errored out" do
before(:each){ module_run.status = MetasploitDataModels::ModuleRun::ERROR}

it{ expect(module_run).to be_valid }
end

end

end
end
end

34 changes: 24 additions & 10 deletions spec/factories/module_runs.rb
Original file line number Diff line number Diff line change
@@ -1,15 +1,29 @@
FactoryGirl.define do
factory :module_run do
trackable_type "MyString"
trackable_id 1
attempted_at "2015-02-19 11:38:21"
sequence(:session_id)

factory :module_run, class: MetasploitDataModels::ModuleRun do

association :user, factory: :mdm_user

trait :failed do
status MetasploitDataModels::ModuleRun::FAIL
end

trait :exploited do
status MetasploitDataModels::ModuleRun::SUCCEED
end

trait :error do
status MetasploitDataModels::ModuleRun::ERROR
end

attempted_at Time.now
session_id 1
port 1
proto "MyString"
fail_detail "MyText"
status "MyString"
username "MyString"
user_id 1
port { generate(:port) }
proto "http"
fail_detail "Failed to execute payload froamasher"
status MetasploitDataModels::ModuleRun::SUCCEED
username "joefoo"
module_name "exploit/windows/happy-stack-smasher"
end
end
Expand Down

0 comments on commit 206cb4b

Please sign in to comment.