diff --git a/documentation/api/v1/credential_api_doc.rb b/documentation/api/v1/credential_api_doc.rb index 647c110cc8..4991db4166 100644 --- a/documentation/api/v1/credential_api_doc.rb +++ b/documentation/api/v1/credential_api_doc.rb @@ -158,12 +158,21 @@ module CredentialApiDoc response 200 do key :description, 'Returns credential data.' schema do - key :type, :array - items do - key :'$ref', :Credential + property :data do + key :type, :array + items do + key :'$ref', :Credential + end end end end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end end # Swagger documentation for /api/v1/credentials POST @@ -197,8 +206,16 @@ module CredentialApiDoc response 200 do key :description, 'Successful operation.' schema do - key :type, :object - key :'$ref', :Credential + property :data do + key :'$ref', :Credential + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel end end end @@ -211,7 +228,7 @@ module CredentialApiDoc parameter :delete_opts response 200 do - key :description, 'Successful operation.' + key :description, 'Returns an array containing the successfully deleted credentials.' schema do key :type, :array items do @@ -219,39 +236,54 @@ module CredentialApiDoc end end end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end end end swagger_path '/api/v1/credentials/{id}' do # Swagger documentation for api/v1/credentials/:id GET - # TODO: Uncomment below when this endpoint is implemented. - # operation :get do - # key :description, 'Return credentials that are stored in the database.' - # key :tags, [ 'credential' ] - # - # parameter :workspace - # parameter :non_dead - # parameter :address - # - # parameter do - # key :name, :id - # key :in, :path - # key :description, 'ID of credential to retrieve.' - # key :required, true - # key :type, :integer - # key :format, :int32 - # end - # - # response 200 do - # key :description, 'Returns credential data.' - # schema do - # key :type, :array - # items do - # key :'$ref', :Credential - # end - # end - # end - # end + operation :get do + key :description, 'Return credential that is stored in the database.' + key :tags, [ 'credential' ] + + parameter :workspace + parameter :non_dead + parameter :address + + parameter do + key :name, :id + key :in, :path + key :description, 'ID of credential to retrieve.' + key :required, true + key :type, :integer + key :format, :int32 + end + + response 200 do + key :description, 'Returns credential data.' + schema do + property :data do + key :type, :array + items do + key :'$ref', :Credential + end + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end + end #Swagger documentation for /api/v1/credentials/:id PUT operation :put do @@ -273,8 +305,16 @@ module CredentialApiDoc response 200 do key :description, 'Successful operation.' schema do - key :type, :object - key :'$ref', :Credential + property :data do + key :'$ref', :Credential + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel end end end diff --git a/documentation/api/v1/db_export_api_doc.rb b/documentation/api/v1/db_export_api_doc.rb index 7c1a33c4d1..e3f0b9841d 100644 --- a/documentation/api/v1/db_export_api_doc.rb +++ b/documentation/api/v1/db_export_api_doc.rb @@ -28,11 +28,20 @@ module DbExportApiDoc response 200 do key :description, 'A JSON object containing the Base64 encoded backup file.' schema do - property :db_export_file do - key :type, :string + property :data do + property :db_export_file do + key :type, :string + end end end end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end end end end diff --git a/documentation/api/v1/event_api_doc.rb b/documentation/api/v1/event_api_doc.rb index a67a59d114..3049265568 100644 --- a/documentation/api/v1/event_api_doc.rb +++ b/documentation/api/v1/event_api_doc.rb @@ -50,8 +50,16 @@ module EventApiDoc response 200 do key :description, 'Successful operation.' schema do - key :type, :object - key :'$ref', :Event + property :data do + key :'$ref', :Event + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel end end end diff --git a/documentation/api/v1/exploit_api_doc.rb b/documentation/api/v1/exploit_api_doc.rb index 36363e3450..4f9eda6d50 100644 --- a/documentation/api/v1/exploit_api_doc.rb +++ b/documentation/api/v1/exploit_api_doc.rb @@ -58,8 +58,16 @@ module ExploitApiDoc response 200 do key :description, 'Successful operation.' schema do - key :type, :object - key :'$ref', :Exploit + property :data do + key :'$ref', :Exploit + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel end end end diff --git a/documentation/api/v1/host_api_doc.rb b/documentation/api/v1/host_api_doc.rb index 665af483eb..ef152f6543 100644 --- a/documentation/api/v1/host_api_doc.rb +++ b/documentation/api/v1/host_api_doc.rb @@ -104,12 +104,21 @@ module HostApiDoc response 200 do key :description, 'Returns host data.' schema do - key :type, :array - items do - key :'$ref', :Host + property :data do + key :type, :array + items do + key :'$ref', :Host + end end end end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end end # Swagger documentation for /api/v1/hosts POST @@ -153,8 +162,16 @@ module HostApiDoc response 200 do key :description, 'Successful operation.' schema do - key :type, :object - key :'$ref', :Host + property :data do + key :'$ref', :Host + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel end end end @@ -167,14 +184,23 @@ module HostApiDoc parameter :delete_opts response 200 do - key :description, 'Successful operation.' + key :description, 'Returns an array containing the successfully deleted hosts.' schema do - key :type, :array - items do - key :'$ref', :Host + property :data do + key :type, :array + items do + key :'$ref', :Host + end end end end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end end end @@ -184,10 +210,6 @@ module HostApiDoc key :description, 'Return specific host that is stored in the database.' key :tags, [ 'host' ] - parameter :workspace - parameter :non_dead - parameter :address - parameter do key :name, :id key :in, :path @@ -200,12 +222,21 @@ module HostApiDoc response 200 do key :description, 'Returns host data.' schema do - key :type, :array - items do - key :'$ref', :Host + property :data do + key :type, :array + items do + key :'$ref', :Host + end end end end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end end # Swagger documentation for /api/v1/hosts/:id PUT @@ -226,10 +257,18 @@ module HostApiDoc end response 200 do - key :description, 'Successful operation.' + key :description, 'Returns host data.' schema do - key :type, :object - key :'$ref', :Host + property :data do + key :'$ref', :Host + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel end end end diff --git a/documentation/api/v1/login_api_doc.rb b/documentation/api/v1/login_api_doc.rb index bc1919032b..1dc1dabf3b 100644 --- a/documentation/api/v1/login_api_doc.rb +++ b/documentation/api/v1/login_api_doc.rb @@ -52,12 +52,21 @@ module LoginApiDoc response 200 do key :description, 'Returns login data.' schema do - key :type, :array - items do - key :'$ref', :Login + property :data do + key :type, :array + items do + key :'$ref', :Login + end end end end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end end # Swagger documentation for /api/v1/logins POST @@ -86,8 +95,16 @@ module LoginApiDoc response 200 do key :description, 'Successful operation.' schema do - key :type, :object - key :'$ref', :Login + property :data do + key :'$ref', :Login + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel end end end @@ -100,11 +117,13 @@ module LoginApiDoc parameter :delete_opts response 200 do - key :description, 'Successful operation.' + key :description, 'Returns an array containing the successfully deleted logins.' schema do - key :type, :array - items do - key :'$ref', :Login + property :data do + key :type, :array + items do + key :'$ref', :Login + end end end end @@ -112,6 +131,40 @@ module LoginApiDoc end swagger_path '/api/v1/logins/{id}' do + # Swagger documentation for api/v1/logins/:id GET + operation :get do + key :description, 'Return specific login that is stored in the database.' + key :tags, [ 'login' ] + + parameter do + key :name, :id + key :in, :path + key :description, 'ID of login to retrieve.' + key :required, true + key :type, :integer + key :format, :int32 + end + + response 200 do + key :description, 'Returns login data.' + schema do + property :data do + key :type, :array + items do + key :'$ref', :Login + end + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end + end + # Swagger documentation for /api/v1/logins/:id PUT operation :put do key :description, 'Update the attributes an existing login.' @@ -132,8 +185,16 @@ module LoginApiDoc response 200 do key :description, 'Successful operation.' schema do - key :type, :object - key :'$ref', :Login + property :data do + key :'$ref', :Login + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel end end end diff --git a/documentation/api/v1/loot_api_doc.rb b/documentation/api/v1/loot_api_doc.rb index b0795a5680..59d822ab2f 100644 --- a/documentation/api/v1/loot_api_doc.rb +++ b/documentation/api/v1/loot_api_doc.rb @@ -48,12 +48,21 @@ module LootApiDoc response 200 do key :description, 'Returns loot data.' schema do - key :type, :array - items do - key :'$ref', :Loot + property :data do + key :type, :array + items do + key :'$ref', :Loot + end end end end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end end # Swagger documentation for /api/v1/loots POST @@ -82,8 +91,16 @@ module LootApiDoc response 200 do key :description, 'Successful operation.' schema do - key :type, :object - key :'$ref', :Loot + property :data do + key :'$ref', :Loot + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel end end end @@ -96,49 +113,62 @@ module LootApiDoc parameter :delete_opts response 200 do - key :description, 'Successful operation.' + key :description, 'Returns an array containing the successfully deleted loot.' schema do - key :type, :array - items do - key :'$ref', :Loot + property :data do + key :type, :array + items do + key :'$ref', :Loot + end end end end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end end end - swagger_path '/api/v1/loot/{id}' do - # Swagger documentation for api/v1/loot/:id GET + swagger_path '/api/v1/loots/{id}' do + # Swagger documentation for api/v1/loots/:id GET + operation :get do + key :description, 'Return specific loot entry that is stored in the database.' + key :tags, [ 'loot' ] - # TODO: Add this back in when this endpoint is implemented, tracked in MS-3233. - # - # operation :get do - # key :description, 'Return specific loot entry that is stored in the database.' - # key :tags, [ 'loot' ] - # - # parameter :workspace - # - # parameter do - # key :name, :id - # key :in, :path - # key :description, 'ID of loot to retrieve.' - # key :required, true - # key :type, :integer - # key :format, :int32 - # end - # - # response 200 do - # key :description, 'Returns loot data.' - # schema do - # key :type, :array - # items do - # key :'$ref', :Loot - # end - # end - # end - # end + parameter do + key :name, :id + key :in, :path + key :description, 'ID of loot to retrieve.' + key :required, true + key :type, :integer + key :format, :int32 + end - # Swagger documentation for /api/v1/loot/{id} PUT + response 200 do + key :description, 'Returns loot data.' + schema do + property :data do + key :type, :array + items do + key :'$ref', :Loot + end + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end + end + + # Swagger documentation for /api/v1/loots/{id} PUT operation :put do key :description, 'Update the attributes an existing loot.' key :tags, [ 'loot' ] @@ -158,8 +188,16 @@ module LootApiDoc response 200 do key :description, 'Successful operation.' schema do - key :type, :object - key :'$ref', :Loot + property :data do + key :'$ref', :Loot + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel end end end diff --git a/documentation/api/v1/msf_api_doc.rb b/documentation/api/v1/msf_api_doc.rb index 49f2dc5ef9..a5701710ec 100644 --- a/documentation/api/v1/msf_api_doc.rb +++ b/documentation/api/v1/msf_api_doc.rb @@ -12,7 +12,16 @@ module MsfApiDoc response 200 do key :description, 'Returns the Metasploit Framework version.' schema do - property :metasploit_version, type: :string + property :data do + property :metasploit_version, type: :string + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel end end end diff --git a/documentation/api/v1/nmap_api_doc.rb b/documentation/api/v1/nmap_api_doc.rb index 6fdc48d0bf..349ac24091 100644 --- a/documentation/api/v1/nmap_api_doc.rb +++ b/documentation/api/v1/nmap_api_doc.rb @@ -28,6 +28,13 @@ module NmapApiDoc end end end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end end end end diff --git a/documentation/api/v1/note_api_doc.rb b/documentation/api/v1/note_api_doc.rb index a401c75b4d..17b20a8e1d 100644 --- a/documentation/api/v1/note_api_doc.rb +++ b/documentation/api/v1/note_api_doc.rb @@ -40,12 +40,21 @@ module NoteApiDoc response 200 do key :description, 'Returns note data.' schema do - key :type, :array - items do - key :'$ref', :Note + property :data do + key :type, :array + items do + key :'$ref', :Note + end end end end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end end # Swagger documentation for /api/v1/notes POST @@ -71,8 +80,16 @@ module NoteApiDoc response 200 do key :description, 'Successful operation.' schema do - key :type, :object - key :'$ref', :Note + property :data do + key :'$ref', :Note + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel end end end @@ -85,14 +102,23 @@ module NoteApiDoc parameter :delete_opts response 200 do - key :description, 'Successful operation.' + key :description, 'Returns an array containing the successfully deleted notes.' schema do - key :type, :array - items do - key :'$ref', :Note + property :data do + key :type, :array + items do + key :'$ref', :Note + end end end end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end end end @@ -102,8 +128,6 @@ module NoteApiDoc key :description, 'Return specific note that is stored in the database.' key :tags, [ 'note' ] - parameter :workspace - parameter do key :name, :id key :in, :path @@ -114,14 +138,23 @@ module NoteApiDoc end response 200 do - key :description, 'Returns notes data.' + key :description, 'Returns note data.' schema do - key :type, :array - items do - key :'$ref', :Note + property :data do + key :type, :array + items do + key :'$ref', :Note + end end end end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end end # Swagger documentation for /api/v1/notes/:id PUT @@ -144,8 +177,16 @@ module NoteApiDoc response 200 do key :description, 'Successful operation.' schema do - key :type, :object - key :'$ref', :Note + property :data do + key :'$ref', :Note + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel end end end diff --git a/documentation/api/v1/root_api_doc.rb b/documentation/api/v1/root_api_doc.rb index e7aaab95c4..418203421c 100644 --- a/documentation/api/v1/root_api_doc.rb +++ b/documentation/api/v1/root_api_doc.rb @@ -10,6 +10,10 @@ module RootApiDoc WORKSPACE_POST_DESC = 'The name of the workspace where this record should be created.' WORKSPACE_POST_EXAMPLE = 'default' HOST_EXAMPLE = '127.0.0.1' + CODE_DESC = 'The error code that was generated.' + CODE_EXAMPLE = 500 + MESSAGE_DESC = 'A message describing the error that occurred.' + MESSAGE_EXAMPLE = 'Undefined method \'empty?\' for nil:NilClass' swagger_root do key :swagger, '2.0' @@ -107,4 +111,20 @@ module RootApiDoc key :type, :string end end + + swagger_schema :ErrorModel do + key :required, [:message] + property :error do + property :code do + key :type, :int32 + key :description, CODE_DESC + key :example, CODE_EXAMPLE + end + property :message do + key :type, :string + key :description, MESSAGE_DESC + key :example, MESSAGE_EXAMPLE + end + end + end end \ No newline at end of file diff --git a/documentation/api/v1/service_api_doc.rb b/documentation/api/v1/service_api_doc.rb index 298181b559..e3b629a1f5 100644 --- a/documentation/api/v1/service_api_doc.rb +++ b/documentation/api/v1/service_api_doc.rb @@ -41,12 +41,21 @@ module ServiceApiDoc response 200 do key :description, 'Returns service data.' schema do - key :type, :array - items do - key :'$ref', :Service + property :data do + key :type, :array + items do + key :'$ref', :Service + end end end end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end end # Swagger documentation for /api/v1/services POST @@ -73,8 +82,16 @@ module ServiceApiDoc response 200 do key :description, 'Successful operation.' schema do - key :type, :object - key :'$ref', :Service + property :data do + key :'$ref', :Service + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel end end end @@ -87,47 +104,61 @@ module ServiceApiDoc parameter :delete_opts response 200 do - key :description, 'Successful operation.' + key :description, 'Returns an array containing the successfully deleted services.' schema do - key :type, :array - items do - key :'$ref', :Service + property :data do + key :type, :array + items do + key :'$ref', :Service + end end end end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end end end swagger_path '/api/v1/services/{id}' do # Swagger documentation for api/v1/services/:id GET - # TODO: Add this back in when this endpoint is implemented, tracked in MS-3233. - # - # operation :get do - # key :description, 'Return specific service that is stored in the database.' - # key :tags, [ 'service' ] - # - # parameter :workspace - # - # parameter do - # key :name, :id - # key :in, :path - # key :description, 'ID of service to retrieve.' - # key :required, true - # key :type, :integer - # key :format, :int32 - # end - # - # response 200 do - # key :description, 'Returns service data.' - # schema do - # key :type, :array - # items do - # key :'$ref', :Service - # end - # end - # end - # end + operation :get do + key :description, 'Return specific service that is stored in the database.' + key :tags, [ 'service' ] + + parameter do + key :name, :id + key :in, :path + key :description, 'ID of service to retrieve.' + key :required, true + key :type, :integer + key :format, :int32 + end + + response 200 do + key :description, 'Returns service data.' + schema do + property :data do + key :type, :array + items do + key :'$ref', :Service + end + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end + end # Swagger documentation for /api/v1/services/:id PUT operation :put do @@ -149,8 +180,16 @@ module ServiceApiDoc response 200 do key :description, 'Successful operation.' schema do - key :type, :object - key :'$ref', :Service + property :data do + key :'$ref', :Service + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel end end end diff --git a/documentation/api/v1/session_api_doc.rb b/documentation/api/v1/session_api_doc.rb index 20f3a88b19..c1c96707f5 100644 --- a/documentation/api/v1/session_api_doc.rb +++ b/documentation/api/v1/session_api_doc.rb @@ -32,12 +32,21 @@ module SessionApiDoc response 200 do key :description, 'Returns session data.' schema do - key :type, :array - items do - key :'$ref', :Session + property :data do + key :type, :array + items do + key :'$ref', :Session + end end end end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end end # Swagger documentation for /api/v1/sessions POST @@ -68,4 +77,40 @@ module SessionApiDoc # end # end end + + swagger_path '/api/v1/sessions/{id}' do + # Swagger documentation for api/v1/sessions/:id GET + operation :get do + key :description, 'Return a specific session that is stored in the database.' + key :tags, [ 'session' ] + + parameter do + key :name, :id + key :in, :path + key :description, 'ID of session to retrieve.' + key :required, true + key :type, :integer + key :format, :int32 + end + + response 200 do + key :description, 'Returns session data.' + schema do + property :data do + key :type, :array + items do + key :'$ref', :Session + end + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end + end + end end diff --git a/documentation/api/v1/session_event_api_doc.rb b/documentation/api/v1/session_event_api_doc.rb index 8f740c1605..8811a37a16 100644 --- a/documentation/api/v1/session_event_api_doc.rb +++ b/documentation/api/v1/session_event_api_doc.rb @@ -35,12 +35,21 @@ module SessionEventApiDoc response 200 do key :description, 'Returns session event data.' schema do - key :type, :array - items do - key :'$ref', :SessionEvent + property :data do + key :type, :array + items do + key :'$ref', :SessionEvent + end end end end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end end # Swagger documentation for /api/v1/session events POST @@ -66,8 +75,52 @@ module SessionEventApiDoc response 200 do key :description, 'Successful operation.' schema do - key :type, :object - key :'$ref', :SessionEvent + property :data do + key :'$ref', :SessionEvent + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end + end + end + + swagger_path '/api/v1/session-events/{id}' do + # Swagger documentation for api/v1/session-events/:id GET + operation :get do + key :description, 'Return a specific session_event that is stored in the database.' + key :tags, [ 'session_event' ] + + parameter do + key :name, :id + key :in, :path + key :description, 'ID of session_event to retrieve.' + key :required, true + key :type, :integer + key :format, :int32 + end + + response 200 do + key :description, 'Returns session event data.' + schema do + property :data do + key :type, :array + items do + key :'$ref', :SessionEvent + end + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel end end end diff --git a/documentation/api/v1/vuln_api_doc.rb b/documentation/api/v1/vuln_api_doc.rb index 35bbda65f9..17030505a4 100644 --- a/documentation/api/v1/vuln_api_doc.rb +++ b/documentation/api/v1/vuln_api_doc.rb @@ -89,12 +89,21 @@ module VulnApiDoc response 200 do key :description, 'Returns vuln data.' schema do - key :type, :array - items do - key :'$ref', :Vuln + property :data do + key :type, :array + items do + key :'$ref', :Vuln + end end end end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end end # Swagger documentation for /api/v1/vulns POST @@ -124,10 +133,18 @@ module VulnApiDoc end response 200 do - key :description, 'Successful operation.' + key :description, 'Returns vuln data.' schema do - key :type, :object - key :'$ref', :Vuln + property :data do + key :'$ref', :Vuln + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel end end end @@ -140,14 +157,23 @@ module VulnApiDoc parameter :delete_opts response 200 do - key :description, 'Successful operation.' + key :description, 'Returns an array containing the successfully deleted vulns.' schema do - key :type, :array - items do - key :'$ref', :Vuln + property :data do + key :type, :array + items do + key :'$ref', :Vuln + end end end end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end end end @@ -157,8 +183,6 @@ module VulnApiDoc key :description, 'Return specific vuln that is stored in the database.' key :tags, [ 'vuln' ] - parameter :workspace - parameter do key :name, :id key :in, :path @@ -171,12 +195,21 @@ module VulnApiDoc response 200 do key :description, 'Returns vuln data.' schema do - key :type, :array - items do - key :'$ref', :Vuln + property :data do + key :type, :array + items do + key :'$ref', :Vuln + end end end end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end end # Swagger documentation for /api/v1/vulns/:id PUT @@ -197,10 +230,18 @@ module VulnApiDoc end response 200 do - key :description, 'Successful operation.' + key :description, 'Returns vuln data.' schema do - key :type, :object - key :'$ref', :Vuln + property :data do + key :'$ref', :Vuln + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel end end end diff --git a/documentation/api/v1/vuln_attempt_api_doc.rb b/documentation/api/v1/vuln_attempt_api_doc.rb index f9a9bed8ad..798df1c70e 100644 --- a/documentation/api/v1/vuln_attempt_api_doc.rb +++ b/documentation/api/v1/vuln_attempt_api_doc.rb @@ -41,12 +41,21 @@ module VulnAttemptApiDoc response 200 do key :description, 'Returns vuln attempt data.' schema do - key :type, :array - items do - key :'$ref', :VulnAttempt + property :data do + key :type, :array + items do + key :'$ref', :VulnAttempt + end end end end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end end # Swagger documentation for /api/v1/vuln-attempts POST @@ -74,8 +83,52 @@ module VulnAttemptApiDoc response 200 do key :description, 'Successful operation.' schema do - key :type, :object - key :'$ref', :VulnAttempt + property :data do + key :'$ref', :VulnAttempt + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end + end + end + + swagger_path '/api/v1/vuln-attempts/{id}' do + # Swagger documentation for api/v1/vuln-attempts/:id GET + operation :get do + key :description, 'Return a specific vuln attempt that is stored in the database.' + key :tags, [ 'vuln_attempt' ] + + parameter do + key :name, :id + key :in, :path + key :description, 'ID of vuln attempt to retrieve.' + key :required, true + key :type, :integer + key :format, :int32 + end + + response 200 do + key :description, 'Returns vuln attempt data.' + schema do + property :data do + key :type, :array + items do + key :'$ref', :VulnAttempt + end + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel end end end diff --git a/documentation/api/v1/workspace_api_doc.rb b/documentation/api/v1/workspace_api_doc.rb index 9b046aa43f..22b26e9f87 100644 --- a/documentation/api/v1/workspace_api_doc.rb +++ b/documentation/api/v1/workspace_api_doc.rb @@ -34,12 +34,21 @@ module WorkspaceApiDoc response 200 do key :description, 'Returns workspace data.' schema do - key :type, :array - items do - key :'$ref', :Workspace + property :data do + key :type, :array + items do + key :'$ref', :Workspace + end end end end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end end # Swagger documentation for /api/v1/workspaces POST @@ -60,8 +69,16 @@ module WorkspaceApiDoc response 200 do key :description, 'Successful operation.' schema do - key :type, :object - key :'$ref', :Workspace + property :data do + key :'$ref', :Workspace + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel end end end @@ -74,14 +91,23 @@ module WorkspaceApiDoc parameter :delete_opts response 200 do - key :description, 'Successful operation.' + key :description, 'Returns an array containing the successfully deleted workspaces.' schema do - key :type, :array - items do - key :'$ref', :Workspace + property :data do + key :type, :array + items do + key :'$ref', :Workspace + end end end end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end end end @@ -103,12 +129,21 @@ module WorkspaceApiDoc response 200 do key :description, 'Returns workspace data.' schema do - key :type, :array - items do - key :'$ref', :Workspace + property :data do + key :type, :array + items do + key :'$ref', :Workspace + end end end end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel + end + end end # Swagger documentation for /api/v1/workspaces/:id PUT @@ -131,8 +166,16 @@ module WorkspaceApiDoc response 200 do key :description, 'Successful operation.' schema do - key :type, :object - key :'$ref', :Workspace + property :data do + key :'$ref', :Workspace + end + end + end + + response 500 do + key :description, 'An error occurred during the operation. See the message for more details.' + schema do + key :'$ref', :ErrorModel end end end diff --git a/lib/metasploit/framework/data_service/proxy/core.rb b/lib/metasploit/framework/data_service/proxy/core.rb index bd1518c473..83a1a5b860 100644 --- a/lib/metasploit/framework/data_service/proxy/core.rb +++ b/lib/metasploit/framework/data_service/proxy/core.rb @@ -151,6 +151,9 @@ class DataProxy # @param [String] wspace A specific workspace name to add to the opts hash. # @return [Hash] The opts hash with a valid :workspace value added. def add_opts_workspace(opts, wspace = nil) + # If :id is present the user only wants a specific record, so workspace isn't needed + return if opts.key?(:id) + # Some methods use the key :wspace. Let's standardize on :workspace and clean it up here. opts[:workspace] = opts.delete(:wspace) unless opts[:wspace].nil? diff --git a/lib/metasploit/framework/data_service/proxy/credential_data_proxy.rb b/lib/metasploit/framework/data_service/proxy/credential_data_proxy.rb index ee1a631f8f..7955fcf08e 100644 --- a/lib/metasploit/framework/data_service/proxy/credential_data_proxy.rb +++ b/lib/metasploit/framework/data_service/proxy/credential_data_proxy.rb @@ -15,7 +15,7 @@ module CredentialDataProxy opts[:workspace_id] = workspace.id opts[:private_data] = opts.delete(:password) opts[:private_type] = :password - old_core = data_service.creds(id: opts.delete(:core_id), workspace: workspace.name).first + old_core = data_service.creds(id: opts.delete(:core_id)).first if old_core opts[:originating_core_id] = old_core.id opts[:origin_type] = :cracked_password diff --git a/lib/metasploit/framework/data_service/proxy/host_data_proxy.rb b/lib/metasploit/framework/data_service/proxy/host_data_proxy.rb index 2f703f0561..acc722eb68 100644 --- a/lib/metasploit/framework/data_service/proxy/host_data_proxy.rb +++ b/lib/metasploit/framework/data_service/proxy/host_data_proxy.rb @@ -29,7 +29,7 @@ module HostDataProxy def get_host(opts) begin - data_service = self.get_data_service() + data_service = self.get_data_service data_service.get_host(opts) rescue => e self.log_error(e, "Problem retrieving host") @@ -48,16 +48,6 @@ module HostDataProxy end end - def report_hosts(hosts) - begin - data_service = self.get_data_service - add_opts_workspace(hosts) - data_service.report_hosts(hosts) - rescue => e - self.log_error(e, "Problem reporting hosts") - end - end - def update_host(opts) begin data_service = self.get_data_service diff --git a/lib/metasploit/framework/data_service/remote/http/core.rb b/lib/metasploit/framework/data_service/remote/http/core.rb index 0c7975ce28..4685218350 100644 --- a/lib/metasploit/framework/data_service/remote/http/core.rb +++ b/lib/metasploit/framework/data_service/remote/http/core.rb @@ -204,6 +204,22 @@ class RemoteHTTPDataService return false end + # Select the correct path for GET request based on the options parameters provided. + # If 'id' is present, the user is requesting a single record and should use + # api///ID path. + # + # @param [Hash] opts The parameters for the request + # @param [String] path The base resource path for the endpoint + # + # @return [String] The correct path for the request. + def get_path_select(opts, path) + if opts.key?(:id) + path = "#{path}/#{opts[:id]}" + opts.delete(:id) + end + path + end + ######### protected ######### diff --git a/lib/metasploit/framework/data_service/remote/http/remote_credential_data_service.rb b/lib/metasploit/framework/data_service/remote/http/remote_credential_data_service.rb index 273a023e89..4b7d30a6f9 100644 --- a/lib/metasploit/framework/data_service/remote/http/remote_credential_data_service.rb +++ b/lib/metasploit/framework/data_service/remote/http/remote_credential_data_service.rb @@ -8,17 +8,15 @@ module RemoteCredentialDataService CREDENTIAL_MDM_CLASS = 'Metasploit::Credential::Core' def creds(opts = {}) - data = self.get_data(CREDENTIAL_API_PATH, nil, opts) + path = get_path_select(opts, CREDENTIAL_API_PATH) + data = self.get_data(path, nil, opts) rv = json_to_mdm_object(data, CREDENTIAL_MDM_CLASS, []) - parsed_body = JSON.parse(data.response.body) - parsed_body.each do |cred| - if cred['private'] - private_object = to_ar(cred['private']['type'].constantize, cred['private']) - rv[parsed_body.index(cred)].private = private_object - end + parsed_body = JSON.parse(data.response.body).symbolize_keys + data = parsed_body[:data] + data.each do |cred| if cred['origin'] origin_object = to_ar(cred['origin']['type'].constantize, cred['origin']) - rv[parsed_body.index(cred)].origin = origin_object + rv[data.index(cred)].origin = origin_object end end rv diff --git a/lib/metasploit/framework/data_service/remote/http/remote_host_data_service.rb b/lib/metasploit/framework/data_service/remote/http/remote_host_data_service.rb index a23a55ddc7..834227f822 100644 --- a/lib/metasploit/framework/data_service/remote/http/remote_host_data_service.rb +++ b/lib/metasploit/framework/data_service/remote/http/remote_host_data_service.rb @@ -8,7 +8,8 @@ module RemoteHostDataService HOST_MDM_CLASS = 'Mdm::Host' def hosts(opts) - json_to_mdm_object(self.get_data(HOST_API_PATH, nil, opts), HOST_MDM_CLASS, []) + path = get_path_select(opts, HOST_API_PATH) + json_to_mdm_object(self.get_data(path, nil, opts), HOST_MDM_CLASS, []) end def get_host(opts) @@ -19,10 +20,6 @@ module RemoteHostDataService json_to_mdm_object(self.post_data(HOST_API_PATH, opts), HOST_MDM_CLASS, []).first end - def report_hosts(hosts) - self.post_data(HOST_API_PATH, hosts) - end - def update_host(opts) path = HOST_API_PATH if opts && opts[:id] @@ -35,10 +32,4 @@ module RemoteHostDataService def delete_host(opts) json_to_mdm_object(self.delete_data(HOST_API_PATH, opts), HOST_MDM_CLASS, []) end - - # TODO: Remove? What is the purpose of this method? - def do_host_search(search) - response = self.post_data(HOST_SEARCH_PATH, search) - return response.body - end end \ No newline at end of file diff --git a/lib/metasploit/framework/data_service/remote/http/remote_login_data_service.rb b/lib/metasploit/framework/data_service/remote/http/remote_login_data_service.rb index 3d4f7371c3..33c6606dc8 100644 --- a/lib/metasploit/framework/data_service/remote/http/remote_login_data_service.rb +++ b/lib/metasploit/framework/data_service/remote/http/remote_login_data_service.rb @@ -8,7 +8,8 @@ module RemoteLoginDataService LOGIN_MDM_CLASS = 'Metasploit::Credential::Login' def logins(opts) - json_to_mdm_object(self.get_data(LOGIN_API_PATH, opts), LOGIN_MDM_CLASS, []) + path = get_path_select(opts, LOGIN_API_PATH) + json_to_mdm_object(self.get_data(path, nil, opts), LOGIN_MDM_CLASS, []) end def create_credential_login(opts) diff --git a/lib/metasploit/framework/data_service/remote/http/remote_loot_data_service.rb b/lib/metasploit/framework/data_service/remote/http/remote_loot_data_service.rb index 65f4b465c8..313f1b6919 100644 --- a/lib/metasploit/framework/data_service/remote/http/remote_loot_data_service.rb +++ b/lib/metasploit/framework/data_service/remote/http/remote_loot_data_service.rb @@ -7,8 +7,9 @@ module RemoteLootDataService LOOT_MDM_CLASS = 'Mdm::Loot' def loot(opts = {}) + path = get_path_select(opts, LOOT_API_PATH) # TODO: Add an option to toggle whether the file data is returned or not - loots = json_to_mdm_object(self.get_data(LOOT_API_PATH, nil, opts), LOOT_MDM_CLASS, []) + loots = json_to_mdm_object(self.get_data(path, nil, opts), LOOT_MDM_CLASS, []) # Save a local copy of the file loots.each do |loot| if loot.data @@ -23,10 +24,6 @@ module RemoteLootDataService self.post_data_async(LOOT_API_PATH, opts) end - def report_loots(loot) - self.post_data(LOOT_API_PATH, loot) - end - def update_loot(opts) path = LOOT_API_PATH if opts && opts[:id] diff --git a/lib/metasploit/framework/data_service/remote/http/remote_note_data_service.rb b/lib/metasploit/framework/data_service/remote/http/remote_note_data_service.rb index e8a33e73a6..3e555a31f4 100644 --- a/lib/metasploit/framework/data_service/remote/http/remote_note_data_service.rb +++ b/lib/metasploit/framework/data_service/remote/http/remote_note_data_service.rb @@ -7,7 +7,8 @@ module RemoteNoteDataService NOTE_MDM_CLASS = 'Mdm::Note' def notes(opts) - json_to_mdm_object(self.get_data(NOTE_API_PATH, nil, opts), NOTE_MDM_CLASS, []) + path = get_path_select(opts, NOTE_API_PATH) + json_to_mdm_object(self.get_data(path, nil, opts), NOTE_MDM_CLASS, []) end def report_note(opts) diff --git a/lib/metasploit/framework/data_service/remote/http/remote_service_data_service.rb b/lib/metasploit/framework/data_service/remote/http/remote_service_data_service.rb index 452f2cb836..f58c559503 100644 --- a/lib/metasploit/framework/data_service/remote/http/remote_service_data_service.rb +++ b/lib/metasploit/framework/data_service/remote/http/remote_service_data_service.rb @@ -3,7 +3,8 @@ module RemoteServiceDataService SERVICE_MDM_CLASS = 'Mdm::Service' def services(opts) - json_to_mdm_object(self.get_data(SERVICE_API_PATH, nil, opts), SERVICE_MDM_CLASS, []) + path = get_path_select(opts, SERVICE_API_PATH) + json_to_mdm_object(self.get_data(path, nil, opts), SERVICE_MDM_CLASS, []) end def report_service(opts) diff --git a/lib/metasploit/framework/data_service/remote/http/remote_session_data_service.rb b/lib/metasploit/framework/data_service/remote/http/remote_session_data_service.rb index 87d34ca1c9..c6c8c83b0c 100644 --- a/lib/metasploit/framework/data_service/remote/http/remote_session_data_service.rb +++ b/lib/metasploit/framework/data_service/remote/http/remote_session_data_service.rb @@ -7,7 +7,8 @@ module RemoteSessionDataService SESSION_MDM_CLASS = 'Mdm::Session' def sessions(opts) - json_to_mdm_object(self.get_data(SESSION_API_PATH, nil, opts), SESSION_MDM_CLASS, []) + path = get_path_select(opts, SESSION_API_PATH) + json_to_mdm_object(self.get_data(path, nil, opts), SESSION_MDM_CLASS, []) end def report_session(opts) @@ -41,14 +42,6 @@ module RemoteSessionDataService return hash end - def parse_host_opts(msf_session) - hash = Hash.new() - hash[:host] = msf_session.session_host - hash[:arch] = msf_session.arch if msf_session.respond_to?(:arch) and msf_session.arch - hash[:workspace] = msf_session[:workspace] || msf_session.workspace - return hash - end - def parse_session_data(msf_session) hash = Hash.new() # TODO: what to do with this shiz diff --git a/lib/metasploit/framework/data_service/remote/http/remote_session_event_data_service.rb b/lib/metasploit/framework/data_service/remote/http/remote_session_event_data_service.rb index 5f7f9e730f..4fc87c13de 100644 --- a/lib/metasploit/framework/data_service/remote/http/remote_session_event_data_service.rb +++ b/lib/metasploit/framework/data_service/remote/http/remote_session_event_data_service.rb @@ -7,7 +7,8 @@ module RemoteSessionEventDataService SESSION_EVENT_MDM_CLASS = 'Mdm::SessionEvent' def session_events(opts = {}) - json_to_mdm_object(self.get_data(SESSION_EVENT_API_PATH, opts), SESSION_EVENT_MDM_CLASS, []) + path = get_path_select(opts, SESSION_EVENT_API_PATH) + json_to_mdm_object(self.get_data(path, nil, opts), SESSION_EVENT_MDM_CLASS, []) end def report_session_event(opts) diff --git a/lib/metasploit/framework/data_service/remote/http/remote_vuln_attempt_data_service.rb b/lib/metasploit/framework/data_service/remote/http/remote_vuln_attempt_data_service.rb index 552f63ced5..fe0f534561 100644 --- a/lib/metasploit/framework/data_service/remote/http/remote_vuln_attempt_data_service.rb +++ b/lib/metasploit/framework/data_service/remote/http/remote_vuln_attempt_data_service.rb @@ -7,7 +7,8 @@ module RemoteVulnAttemptDataService VULN_ATTEMPT_MDM_CLASS = 'Mdm::VulnAttempt' def vuln_attempts(opts) - json_to_mdm_object(self.get_data(VULN_ATTEMPT_API_PATH, nil, opts), VULN_ATTEMPT_MDM_CLASS, []) + path = get_path_select(opts, VULN_ATTEMPT_API_PATH) + json_to_mdm_object(self.get_data(path, nil, opts), VULN_ATTEMPT_MDM_CLASS, []) end def report_vuln_attempt(vuln, opts) diff --git a/lib/metasploit/framework/data_service/remote/http/remote_vuln_data_service.rb b/lib/metasploit/framework/data_service/remote/http/remote_vuln_data_service.rb index ef846c68e8..cddfe13938 100644 --- a/lib/metasploit/framework/data_service/remote/http/remote_vuln_data_service.rb +++ b/lib/metasploit/framework/data_service/remote/http/remote_vuln_data_service.rb @@ -7,7 +7,8 @@ module RemoteVulnDataService VULN_MDM_CLASS = 'Mdm::Vuln' def vulns(opts) - json_to_mdm_object(self.get_data(VULN_API_PATH, nil, opts), VULN_MDM_CLASS, []) + path = get_path_select(opts, VULN_API_PATH) + json_to_mdm_object(self.get_data(path, nil, opts), VULN_MDM_CLASS, []) end def report_vuln(opts) diff --git a/lib/metasploit/framework/data_service/remote/http/remote_workspace_data_service.rb b/lib/metasploit/framework/data_service/remote/http/remote_workspace_data_service.rb index a9673e9575..8aa3fabf2e 100644 --- a/lib/metasploit/framework/data_service/remote/http/remote_workspace_data_service.rb +++ b/lib/metasploit/framework/data_service/remote/http/remote_workspace_data_service.rb @@ -30,7 +30,8 @@ module RemoteWorkspaceDataService end def workspaces(opts) - json_to_mdm_object(self.get_data(WORKSPACE_API_PATH, nil, opts), WORKSPACE_MDM_CLASS, []) + path = get_path_select(opts, WORKSPACE_API_PATH) + json_to_mdm_object(self.get_data(path, nil, opts), WORKSPACE_MDM_CLASS, []) end def delete_workspaces(opts) diff --git a/lib/metasploit/framework/data_service/remote/http/response_data_helper.rb b/lib/metasploit/framework/data_service/remote/http/response_data_helper.rb index 038239aef2..ec170fc61a 100644 --- a/lib/metasploit/framework/data_service/remote/http/response_data_helper.rb +++ b/lib/metasploit/framework/data_service/remote/http/response_data_helper.rb @@ -26,8 +26,9 @@ module ResponseDataHelper def json_to_hash(response_wrapper) begin body = process_response(response_wrapper) - unless body.nil? || body.empty? - return JSON.parse(body).symbolize_keys + if !body.nil? && !body.empty? + parsed_body = JSON.parse(body, symbolize_names: true) + return parsed_body[:data] end rescue => e elog "Error parsing response as JSON: #{e.message}" @@ -47,17 +48,18 @@ module ResponseDataHelper if response_wrapper.expected begin body = process_response(response_wrapper) - unless body.nil? || body.empty? - parsed_body = Array.wrap(JSON.parse(body)) + if !body.nil? && !body.empty? + parsed_body = JSON.parse(body).symbolize_keys + data = Array.wrap(parsed_body[:data]) rv = [] - parsed_body.each do |json_object| + data.each do |json_object| rv << to_ar(mdm_class.constantize, json_object) end return rv end rescue => e elog "Mdm Object conversion failed #{e.message}" - e.backtrace.each { |line| elog "#{line}\n" } + e.backtrace.each { |line| elog "#{line}" } end end diff --git a/lib/msf/core/db_manager/cred.rb b/lib/msf/core/db_manager/cred.rb index 6cb1ff7311..c816cf1ff8 100644 --- a/lib/msf/core/db_manager/cred.rb +++ b/lib/msf/core/db_manager/cred.rb @@ -3,12 +3,13 @@ module Msf::DBManager::Cred def creds(opts) query = nil ::ActiveRecord::Base.connection_pool.with_connection { + # If :id exists we're looking for a specific record, skip the other stuff + if opts[:id] && !opts[:id].to_s.empty? + return Array.wrap(Metasploit::Credential::Core.find(opts[:id])) + end + wspace = Msf::Util::DBManager.process_opts_workspace(opts, framework) search_term = opts.delete(:search_term) - # If :id exists we're looking for a specific record, skip the other stuff - if opts[:id].present? - return Metasploit::Credential::Core.where(id: opts[:id]) - end query = Metasploit::Credential::Core.where( workspace_id: wspace.id ) query = query.includes(:private, :public, :logins, :realm).references(:private, :public, :logins, :realm) diff --git a/lib/msf/core/db_manager/event.rb b/lib/msf/core/db_manager/event.rb index 6ba12f88dd..373ca70a7c 100644 --- a/lib/msf/core/db_manager/event.rb +++ b/lib/msf/core/db_manager/event.rb @@ -1,6 +1,11 @@ module Msf::DBManager::Event def events(wspace=workspace) ::ActiveRecord::Base.connection_pool.with_connection { + # If we have the ID, there is no point in creating a complex query. + if opts[:id] && !opts[:id].to_s.empty? + return Array.wrap(Mdm::Event.find(opts[:id])) + end + wspace.events.find :all, :order => 'created_at ASC' } end diff --git a/lib/msf/core/db_manager/host.rb b/lib/msf/core/db_manager/host.rb index e55cb4a035..cfb06f279c 100644 --- a/lib/msf/core/db_manager/host.rb +++ b/lib/msf/core/db_manager/host.rb @@ -128,12 +128,16 @@ module Msf::DBManager::Host # Returns a list of all hosts in the database def hosts(opts) ::ActiveRecord::Base.connection_pool.with_connection { + # If we have the ID, there is no point in creating a complex query. + if opts[:id] && !opts[:id].to_s.empty? + return Array.wrap(Mdm::Host.find(opts[:id])) + end + wspace = Msf::Util::DBManager.process_opts_workspace(opts, framework) conditions = {} conditions[:state] = [Msf::HostState::Alive, Msf::HostState::Unknown] if opts[:non_dead] conditions[:address] = opts[:address] if opts[:address] && !opts[:address].empty? - conditions[:id] = opts[:id] if opts[:id] && !opts[:id].empty? if opts[:search_term] && !opts[:search_term].empty? column_search_conditions = Msf::Util::DBManager.create_all_column_search_conditions(Mdm::Host, opts[:search_term]) diff --git a/lib/msf/core/db_manager/http/servlet/credential_servlet.rb b/lib/msf/core/db_manager/http/servlet/credential_servlet.rb index f2119d2eb9..a29481435b 100644 --- a/lib/msf/core/db_manager/http/servlet/credential_servlet.rb +++ b/lib/msf/core/db_manager/http/servlet/credential_servlet.rb @@ -9,7 +9,7 @@ module CredentialServlet end def self.registered(app) - app.get CredentialServlet.api_path, &get_credentials + app.get CredentialServlet.api_path_with_id, &get_credentials app.post CredentialServlet.api_path, &create_credential app.put CredentialServlet.api_path_with_id, &update_credential app.delete CredentialServlet.api_path, &delete_credentials @@ -23,15 +23,21 @@ module CredentialServlet lambda { warden.authenticate! begin - sanitized_params = sanitize_params(params) + sanitized_params = sanitize_params(params, env['rack.request.query_hash']) data = get_db.creds(sanitized_params) - + includes = [:logins, :public, :private, :realm] # Need to append the human attribute into the private sub-object before converting to json # This is normally pulled from a class method from the MetasploitCredential class + response = [] + data.each do |cred| + json = cred.as_json(include: includes).merge(private_class: cred.private.class.to_s) + response << json + end + data = data.first if is_single_object?(data, sanitized_params) response = format_cred_json(data) - set_json_response(response) + set_json_data_response(response: response) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error retrieving credentials:', code: 500) end } end @@ -56,9 +62,9 @@ module CredentialServlet opts[:id] = tmp_params[:id] if tmp_params[:id] data = get_db.update_credential(opts) response = format_cred_json(data) - set_json_response(response.first) + set_json_data_response(response: response.first) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error updating the credential:', code: 500) end } end @@ -68,9 +74,9 @@ module CredentialServlet begin opts = parse_json_request(request, false) data = get_db.delete_credentials(opts) - set_json_response(data) + set_json_data_response(response: data) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error deleting the credential:', code: 500) end } end diff --git a/lib/msf/core/db_manager/http/servlet/db_export_servlet.rb b/lib/msf/core/db_manager/http/servlet/db_export_servlet.rb index 2992a33d34..845f2a7438 100644 --- a/lib/msf/core/db_manager/http/servlet/db_export_servlet.rb +++ b/lib/msf/core/db_manager/http/servlet/db_export_servlet.rb @@ -24,9 +24,9 @@ module DbExportServlet encoded_file = Base64.urlsafe_encode64(File.read(File.expand_path(output_file))) response = {} response[:db_export_file] = encoded_file - set_json_response(response) + set_json_data_response(response: response) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error exporting the database:', code: 500) ensure # Ensure the temporary file gets cleaned up File.delete(opts[:path]) diff --git a/lib/msf/core/db_manager/http/servlet/event_servlet.rb b/lib/msf/core/db_manager/http/servlet/event_servlet.rb index de31af7bba..8284d3225d 100644 --- a/lib/msf/core/db_manager/http/servlet/event_servlet.rb +++ b/lib/msf/core/db_manager/http/servlet/event_servlet.rb @@ -14,9 +14,13 @@ module EventServlet def self.report_event lambda { - warden.authenticate! - job = lambda { |opts| get_db().report_event(opts) } - exec_report_job(request, &job) + begin + warden.authenticate! + job = lambda { |opts| get_db.report_event(opts) } + exec_report_job(request, &job) + rescue => e + print_error_and_create_response(error: e, message: 'There was an error creating the event:', code: 500) + end } end end \ No newline at end of file diff --git a/lib/msf/core/db_manager/http/servlet/exploit_servlet.rb b/lib/msf/core/db_manager/http/servlet/exploit_servlet.rb index ebc3458151..79360f0ae3 100644 --- a/lib/msf/core/db_manager/http/servlet/exploit_servlet.rb +++ b/lib/msf/core/db_manager/http/servlet/exploit_servlet.rb @@ -18,13 +18,13 @@ module ExploitServlet job = lambda { |opts| case opts[:exploit_report_type] when "attempt" - get_db().report_exploit_attempt(opts[:host], opts) + get_db.report_exploit_attempt(opts[:host], opts) when "failure" - get_db().report_exploit_failure(opts) + get_db.report_exploit_failure(opts) when "success" - get_db().report_exploit_success(opts) + get_db.report_exploit_success(opts) end - get_db().report_host(opts) + get_db.report_host(opts) } exec_report_job(request, &job) } diff --git a/lib/msf/core/db_manager/http/servlet/host_servlet.rb b/lib/msf/core/db_manager/http/servlet/host_servlet.rb index db4a3db7e0..cc4c8d7313 100644 --- a/lib/msf/core/db_manager/http/servlet/host_servlet.rb +++ b/lib/msf/core/db_manager/http/servlet/host_servlet.rb @@ -28,13 +28,13 @@ module HostServlet lambda { warden.authenticate! begin - opts = parse_json_request(request, false) - sanitized_params = sanitize_params(params) + sanitized_params = sanitize_params(params, env['rack.request.query_hash']) data = get_db.hosts(sanitized_params) includes = [:loots] - set_json_response(data, includes) + data = data.first if is_single_object?(data, sanitized_params) + set_json_data_response(response: data, includes: includes) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error getting hosts:', code: 500) end } end @@ -44,11 +44,11 @@ module HostServlet warden.authenticate! begin job = lambda { |opts| - data = get_db.report_host(opts) + get_db.report_host(opts) } exec_report_job(request, &job) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error creating the host:', code: 500) end } end @@ -61,9 +61,9 @@ module HostServlet tmp_params = sanitize_params(params) opts[:id] = tmp_params[:id] if tmp_params[:id] data = get_db.update_host(opts) - set_json_response(data) + set_json_data_response(response: data) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error updating the host:', code: 500) end } end @@ -74,9 +74,9 @@ module HostServlet begin opts = parse_json_request(request, false) data = get_db.delete_host(opts) - set_json_response(data) + set_json_data_response(response: data) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error deleting hosts:', code: 500) end } end @@ -87,10 +87,10 @@ module HostServlet warden.authenticate! begin opts = parse_json_request(request, false) - data = get_db().get_host(opts) - set_json_response(data) + data = get_db.get_host(opts) + set_json_data_response(response: data) rescue Exception => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error searching for hosts:', code: 500) end } end diff --git a/lib/msf/core/db_manager/http/servlet/login_servlet.rb b/lib/msf/core/db_manager/http/servlet/login_servlet.rb index bbf73d6a77..1a84015c21 100644 --- a/lib/msf/core/db_manager/http/servlet/login_servlet.rb +++ b/lib/msf/core/db_manager/http/servlet/login_servlet.rb @@ -22,11 +22,12 @@ module LoginServlet def self.get_logins lambda { begin - sanitized_params = sanitize_params(params) - response = get_db.logins(sanitized_params) - set_json_response(response) + sanitized_params = sanitize_params(params, env['rack.request.query_hash']) + data = get_db.logins(sanitized_params) + data = data.first if is_single_object?(data, sanitized_params) + set_json_response(data) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error retrieving logins:', code: 500) end } end @@ -40,7 +41,7 @@ module LoginServlet response = get_db.create_credential_login(opts) set_json_response(response) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error creating the login:', code: 500) end } end @@ -54,7 +55,7 @@ module LoginServlet data = get_db.update_login(opts) set_json_response(data) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error updating the login:', code: 500) end } end @@ -66,7 +67,7 @@ module LoginServlet data = get_db.delete_logins(opts) set_json_response(data) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error deleting the logins:', code: 500) end } end diff --git a/lib/msf/core/db_manager/http/servlet/loot_servlet.rb b/lib/msf/core/db_manager/http/servlet/loot_servlet.rb index 5e7cc4921c..f71e884f26 100644 --- a/lib/msf/core/db_manager/http/servlet/loot_servlet.rb +++ b/lib/msf/core/db_manager/http/servlet/loot_servlet.rb @@ -9,7 +9,7 @@ module LootServlet end def self.registered(app) - app.get LootServlet.api_path, &get_loot + app.get LootServlet.api_path_with_id, &get_loot app.post LootServlet.api_path, &report_loot app.put LootServlet.api_path_with_id, &update_loot app.delete LootServlet.api_path, &delete_loot @@ -23,16 +23,16 @@ module LootServlet lambda { warden.authenticate! begin - opts = parse_json_request(request, false) - sanitized_params = sanitize_params(params) + sanitized_params = sanitize_params(params, env['rack.request.query_hash']) data = get_db.loots(sanitized_params) includes = [:host] data.each do |loot| loot.data = Base64.urlsafe_encode64(loot.data) if loot.data end - set_json_response(data, includes) + data = data.first if is_single_object?(data, sanitized_params) + set_json_data_response(response: data, includes: includes) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error retrieving the loot:', code: 500) end } end @@ -62,9 +62,9 @@ module LootServlet tmp_params = sanitize_params(params) opts[:id] = tmp_params[:id] if tmp_params[:id] data = get_db.update_loot(opts) - set_json_response(data) + set_json_data_response(response: data) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error updating the loot:', code: 500) end } end @@ -75,9 +75,9 @@ module LootServlet begin opts = parse_json_request(request, false) data = get_db.delete_loot(opts) - set_json_response(data) + set_json_data_response(response: data) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error deleting the loot:', code: 500) end } end diff --git a/lib/msf/core/db_manager/http/servlet/msf_servlet.rb b/lib/msf/core/db_manager/http/servlet/msf_servlet.rb index 14cb653e60..ba2a678895 100644 --- a/lib/msf/core/db_manager/http/servlet/msf_servlet.rb +++ b/lib/msf/core/db_manager/http/servlet/msf_servlet.rb @@ -18,8 +18,12 @@ module MsfServlet def self.get_msf_version lambda { - warden.authenticate! - set_json_response({metasploit_version: Metasploit::Framework::VERSION}) + begin + warden.authenticate! + set_json_data_response(response: { metasploit_version: Metasploit::Framework::VERSION }) + rescue => e + print_error_and_create_response(error: e, message: 'There was an error retrieving the version:', code: 500) + end } end diff --git a/lib/msf/core/db_manager/http/servlet/nmap_servlet.rb b/lib/msf/core/db_manager/http/servlet/nmap_servlet.rb index c200fd762b..e8666ab1e5 100644 --- a/lib/msf/core/db_manager/http/servlet/nmap_servlet.rb +++ b/lib/msf/core/db_manager/http/servlet/nmap_servlet.rb @@ -20,7 +20,7 @@ module NmapServlet nmap_file = File.basename(opts[:filename]) nmap_file_path = File.join(Msf::Config.local_directory, nmap_file) opts[:filename] = process_file(opts[:data], nmap_file_path) - get_db().import_nmap_xml_file(opts) + get_db.import_nmap_xml_file(opts) } exec_report_job(request, &job) } diff --git a/lib/msf/core/db_manager/http/servlet/note_servlet.rb b/lib/msf/core/db_manager/http/servlet/note_servlet.rb index cdf560f28b..38c2ea6406 100644 --- a/lib/msf/core/db_manager/http/servlet/note_servlet.rb +++ b/lib/msf/core/db_manager/http/servlet/note_servlet.rb @@ -23,13 +23,13 @@ module NoteServlet lambda { warden.authenticate! begin - opts = parse_json_request(request, false) - sanitized_params = sanitize_params(params) + sanitized_params = sanitize_params(params, env['rack.request.query_hash']) data = get_db.notes(sanitized_params) includes = [:host] - set_json_response(data, includes) + data = data.first if is_single_object?(data, sanitized_params) + set_json_data_response(response: data, includes: includes) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error retrieving notes:', code: 500) end } end @@ -37,14 +37,10 @@ module NoteServlet def self.report_note lambda { warden.authenticate! - begin - job = lambda { |opts| - get_db.report_note(opts) - } - exec_report_job(request, &job) - rescue => e - set_error_on_response(e) - end + job = lambda { |opts| + get_db.report_note(opts) + } + exec_report_job(request, &job) } end @@ -56,9 +52,9 @@ module NoteServlet tmp_params = sanitize_params(params) opts[:id] = tmp_params[:id] if tmp_params[:id] data = get_db.update_note(opts) - set_json_response(data) + set_json_data_response(response: data) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error updating the note:', code: 500) end } end @@ -69,9 +65,9 @@ module NoteServlet begin opts = parse_json_request(request, false) data = get_db.delete_note(opts) - set_json_response(data) + set_json_data_response(response: data) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error deleting the note:', code: 500) end } end diff --git a/lib/msf/core/db_manager/http/servlet/service_servlet.rb b/lib/msf/core/db_manager/http/servlet/service_servlet.rb index 72d072a637..fc91860767 100644 --- a/lib/msf/core/db_manager/http/servlet/service_servlet.rb +++ b/lib/msf/core/db_manager/http/servlet/service_servlet.rb @@ -9,7 +9,7 @@ module ServiceServlet end def self.registered(app) - app.get ServiceServlet.api_path, &get_services + app.get ServiceServlet.api_path_with_id, &get_services app.post ServiceServlet.api_path, &report_service app.put ServiceServlet.api_path_with_id, &update_service app.delete ServiceServlet.api_path, &delete_service @@ -23,12 +23,13 @@ module ServiceServlet lambda { warden.authenticate! begin - opts = sanitize_params(params) - data = get_db.services(opts) + sanitized_params = sanitize_params(params, env['rack.request.query_hash']) + data = get_db.services(sanitized_params) includes = [:host] - set_json_response(data, includes) + data = data.first if is_single_object?(data, sanitized_params) + set_json_data_response(response: data, includes: includes) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error retrieving services:', code: 500) end } end @@ -50,9 +51,9 @@ module ServiceServlet tmp_params = sanitize_params(params) opts[:id] = tmp_params[:id] if tmp_params[:id] data = get_db.update_service(opts) - set_json_response(data) + set_json_data_response(response: data) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error updating the service:', code: 500) end } end @@ -63,9 +64,9 @@ module ServiceServlet begin opts = parse_json_request(request, false) data = get_db.delete_service(opts) - set_json_response(data) + set_json_data_response(response: data) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error deleting the service:', code: 500) end } end diff --git a/lib/msf/core/db_manager/http/servlet/session_event_servlet.rb b/lib/msf/core/db_manager/http/servlet/session_event_servlet.rb index 11931cd5da..ba8d0f628d 100644 --- a/lib/msf/core/db_manager/http/servlet/session_event_servlet.rb +++ b/lib/msf/core/db_manager/http/servlet/session_event_servlet.rb @@ -4,8 +4,12 @@ module SessionEventServlet '/api/v1/session-events' end + def self.api_path_with_id + "#{SessionEventServlet.api_path}/?:id?" + end + def self.registered(app) - app.get SessionEventServlet.api_path, &get_session_event + app.get SessionEventServlet.api_path_with_id, &get_session_event app.post SessionEventServlet.api_path, &report_session_event end @@ -17,11 +21,12 @@ module SessionEventServlet lambda { warden.authenticate! begin - opts = parse_json_request(request, false) - data = get_db.session_events(opts) - set_json_response(data) + sanitized_params = sanitize_params(params, env['rack.request.query_hash']) + data = get_db.session_events(sanitized_params) + data = data.first if is_single_object?(data, sanitized_params) + set_json_data_response(response: data) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error retrieving session events:', code: 500) end } end @@ -29,14 +34,10 @@ module SessionEventServlet def self.report_session_event lambda { warden.authenticate! - begin - job = lambda { |opts| - get_db.report_session_event(opts) - } - exec_report_job(request, &job) - rescue => e - set_error_on_response(e) - end + job = lambda { |opts| + get_db.report_session_event(opts) + } + exec_report_job(request, &job) } end end \ No newline at end of file diff --git a/lib/msf/core/db_manager/http/servlet/session_servlet.rb b/lib/msf/core/db_manager/http/servlet/session_servlet.rb index ceaedea607..d073ca7118 100644 --- a/lib/msf/core/db_manager/http/servlet/session_servlet.rb +++ b/lib/msf/core/db_manager/http/servlet/session_servlet.rb @@ -21,13 +21,13 @@ module SessionServlet lambda { warden.authenticate! begin - opts = parse_json_request(request, false) - sanitized_params = sanitize_params(params) + sanitized_params = sanitize_params(params, env['rack.request.query_hash']) data = get_db.sessions(sanitized_params) includes = [:host] - set_json_response(data, includes) + data = data.first if is_single_object?(data, sanitized_params) + set_json_data_response(response: data, includes: includes) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error retrieving sessions:', code: 500) end } end @@ -45,7 +45,7 @@ module SessionServlet } exec_report_job(request, &job) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error creating the session:', code: 500) end } end diff --git a/lib/msf/core/db_manager/http/servlet/user_servlet.rb b/lib/msf/core/db_manager/http/servlet/user_servlet.rb index c8672fc2ad..243a2748ea 100644 --- a/lib/msf/core/db_manager/http/servlet/user_servlet.rb +++ b/lib/msf/core/db_manager/http/servlet/user_servlet.rb @@ -23,12 +23,12 @@ module UserServlet lambda { warden.authenticate!(scope: :admin_api) begin - opts = parse_json_request(request, false) - sanitized_params = sanitize_params(params) + sanitized_params = sanitize_params(params, env['rack.request.query_hash']) data = get_db.users(sanitized_params) - set_json_response(data) + data = data.first if is_single_object?(data, sanitized_params) + set_json_data_response(response: data) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error retrieving users:', code: 500) end } end @@ -36,14 +36,10 @@ module UserServlet def self.report_user lambda { warden.authenticate!(scope: :admin_api) - begin - job = lambda { |opts| - get_db.report_user(opts) - } - exec_report_job(request, &job) - rescue => e - set_error_on_response(e) - end + job = lambda { |opts| + get_db.report_user(opts) + } + exec_report_job(request, &job) } end @@ -55,9 +51,11 @@ module UserServlet tmp_params = sanitize_params(params) opts[:id] = tmp_params[:id] if tmp_params[:id] data = get_db.update_user(opts) - set_json_response(data) + # Only return the single object if the id parameter is present + data = data.first if !sanitized_params[:id].nil? && data.count == 1 + set_json_data_response(response: data) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error creating the user:', code: 500) end } end @@ -68,9 +66,9 @@ module UserServlet begin opts = parse_json_request(request, false) data = get_db.delete_user(opts) - set_json_response(data) + set_json_data_response(response: data) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error deleting the users:', code: 500) end } end diff --git a/lib/msf/core/db_manager/http/servlet/vuln_attempt_servlet.rb b/lib/msf/core/db_manager/http/servlet/vuln_attempt_servlet.rb index 611d92d6a0..38d5ebf854 100644 --- a/lib/msf/core/db_manager/http/servlet/vuln_attempt_servlet.rb +++ b/lib/msf/core/db_manager/http/servlet/vuln_attempt_servlet.rb @@ -21,11 +21,12 @@ module VulnAttemptServlet lambda { warden.authenticate! begin - opts = parse_json_request(request, false) - data = get_db.vuln_attempts(params.symbolize_keys) - set_json_response(data) + sanitized_params = sanitize_params(params, env['rack.request.query_hash']) + data = get_db.vuln_attempts(sanitized_params) + data = data.first if is_single_object?(data, sanitized_params) + set_json_data_response(response: data) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error retrieving vuln attempts:', code: 500) end } end @@ -33,17 +34,13 @@ module VulnAttemptServlet def self.report_vuln_attempt lambda { warden.authenticate! - begin - job = lambda { |opts| - vuln_id = opts.delete(:vuln_id) - wspace = opts.delete(:workspace) - vuln = get_db.vulns(id: vuln_id, workspace: wspace).first - get_db.report_vuln_attempt(vuln, opts) - } - exec_report_job(request, &job) - rescue => e - set_error_on_response(e) - end + job = lambda { |opts| + vuln_id = opts.delete(:vuln_id) + wspace = opts.delete(:workspace) + vuln = get_db.vulns(id: vuln_id).first + get_db.report_vuln_attempt(vuln, opts) + } + exec_report_job(request, &job) } end end \ No newline at end of file diff --git a/lib/msf/core/db_manager/http/servlet/vuln_servlet.rb b/lib/msf/core/db_manager/http/servlet/vuln_servlet.rb index 22eb3bd6be..bfc0f6e0e8 100644 --- a/lib/msf/core/db_manager/http/servlet/vuln_servlet.rb +++ b/lib/msf/core/db_manager/http/servlet/vuln_servlet.rb @@ -23,13 +23,13 @@ module VulnServlet lambda { warden.authenticate! begin - opts = parse_json_request(request, false) - sanitized_params = sanitize_params(params) + sanitized_params = sanitize_params(params, env['rack.request.query_hash']) data = get_db.vulns(sanitized_params) includes = [:host, :vulns_refs, :refs, :module_refs] - set_json_response(data, includes) + data = data.first if is_single_object?(data, sanitized_params) + set_json_data_response(response: data, includes: includes) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error retrieving vulns:', code: 500) end } end @@ -37,14 +37,10 @@ module VulnServlet def self.report_vuln lambda { warden.authenticate! - begin - job = lambda { |opts| - get_db.report_vuln(opts) - } - exec_report_job(request, &job) - rescue => e - set_error_on_response(e) - end + job = lambda { |opts| + get_db.report_vuln(opts) + } + exec_report_job(request, &job) } end @@ -56,9 +52,9 @@ module VulnServlet tmp_params = sanitize_params(params) opts[:id] = tmp_params[:id] if tmp_params[:id] data = get_db.update_vuln(opts) - set_json_response(data) + set_json_data_response(response: data) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error updating the vuln:', code: 500) end } end @@ -69,9 +65,9 @@ module VulnServlet begin opts = parse_json_request(request, false) data = get_db.delete_vuln(opts) - set_json_response(data) + set_json_data_response(response: data) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error deleting the vulns:', code: 500) end } end diff --git a/lib/msf/core/db_manager/http/servlet/workspace_servlet.rb b/lib/msf/core/db_manager/http/servlet/workspace_servlet.rb index 3abc03bb70..27475735dd 100644 --- a/lib/msf/core/db_manager/http/servlet/workspace_servlet.rb +++ b/lib/msf/core/db_manager/http/servlet/workspace_servlet.rb @@ -23,15 +23,14 @@ module WorkspaceServlet lambda { warden.authenticate! begin - opts = parse_json_request(request, false) includes = nil - sanitized_params = sanitize_params(params) + sanitized_params = sanitize_params(params, env['rack.request.query_hash']) data = get_db.workspaces(sanitized_params) - - set_json_response(data, includes) + data = data.first if is_single_object?(data, sanitized_params) + set_json_data_response(response: data, includes: includes) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error retrieving workspaces:', code: 500) end } end @@ -41,10 +40,10 @@ module WorkspaceServlet warden.authenticate! begin opts = parse_json_request(request, true) - workspace = get_db.add_workspace(opts) - set_json_response(workspace) + data = get_db.add_workspace(opts) + set_json_data_response(response: data) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error creating the workspace:', code: 500) end } end @@ -57,9 +56,9 @@ module WorkspaceServlet tmp_params = sanitize_params(params) opts[:id] = tmp_params[:id] if tmp_params[:id] data = get_db.update_workspace(opts) - set_json_response(data) + set_json_data_response(response: data) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error updating the workspace:', code: 500) end } end @@ -70,9 +69,9 @@ module WorkspaceServlet begin opts = parse_json_request(request, false) data = get_db.delete_workspaces(opts) - set_json_response(data) + set_json_data_response(response: data) rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error deleting the workspaces:', code: 500) end } end diff --git a/lib/msf/core/db_manager/http/servlet_helper.rb b/lib/msf/core/db_manager/http/servlet_helper.rb index b2be04bd33..c86e13cc2c 100644 --- a/lib/msf/core/db_manager/http/servlet_helper.rb +++ b/lib/msf/core/db_manager/http/servlet_helper.rb @@ -13,22 +13,22 @@ module ServletHelper end def set_empty_response - [200, ''] + set_json_data_response(response: '') end def set_json_response(data, includes = nil, code = 200) - headers = {'Content-Type' => 'application/json'} + headers = { 'Content-Type' => 'application/json' } [code, headers, to_json(data, includes)] end def set_json_data_response(response:, includes: nil, code: 200) - data_response = {"data": response} + data_response = { data: response } set_json_response(data_response, includes = includes, code = code) end - def set_json_error_response(response:, includes: nil, code:) - error_response = {"error": response} - set_json_response(error_response, includes = includes, code = code) + def set_json_error_response(response:, code:) + error_response = { error: response } + set_json_response(error_response, nil, code = code) end def set_html_response(data) @@ -47,6 +47,15 @@ module ServletHelper hash.deep_symbolize_keys end + def print_error_and_create_response(error: , message:, code:) + print_error "Error handling request: #{error.message}.", error + error_response = { + code: code, + message: "#{message} #{error.message}" + } + set_json_error_response(response: error_response, code: code) + end + def exec_report_job(request, includes = nil, &job) begin @@ -59,11 +68,11 @@ module ServletHelper return set_empty_response else data = job.call(opts) - return set_json_response(data, includes) + return set_json_data_response(response: data, includes: includes) end rescue => e - set_error_on_response(e) + print_error_and_create_response(error: e, message: 'There was an error creating the record:', code: 500) end end @@ -73,13 +82,33 @@ module ServletHelper # Sinatra injects extra parameters for some reason: https://github.com/sinatra/sinatra/issues/453 # This method cleans those up so we don't have any unexpected values before passing on. + # It also inspects the query string for any invalid parameters. # # @param [Hash] params Hash containing the parameters for the request. + # @param [Hash] query_hash The query_hash variable from the rack request. # @return [Hash] Returns params with symbolized keys and the injected parameters removed. - def sanitize_params(params) + def sanitize_params(params, query_hash = {}) + # Reject id passed as a query parameter for GET requests. + # API standards say path ID should be used for single records. + if query_hash.key?('id') + raise ArgumentError, ("'id' is not a valid query parameter. Please use /api/v1//{ID} instead.") + end params.symbolize_keys.except(:captures, :splat) end + # Determines if this data set should be output as a single object instead of an array. + # + # @param [Array] data Array containing the data to be returned to the user. + # @param [Hash] params The parameters included in the request. + # + # @return [Bool] true if the data should be printed as a single object, false otherwise + def is_single_object?(data, params) + # Check to see if the ID parameter was present. If so, print as a single object. + # Note that ID is not valid as a query parameter, so we assume that the user + # used /{ID} notation if ID is present in params. + !params[:id].nil? && data.count == 1 + end + def format_cred_json(data) includes = [:logins, :public, :private, :realm, :origin] diff --git a/lib/msf/core/db_manager/loot.rb b/lib/msf/core/db_manager/loot.rb index 5af116ad20..0109c2f854 100644 --- a/lib/msf/core/db_manager/loot.rb +++ b/lib/msf/core/db_manager/loot.rb @@ -17,6 +17,11 @@ module Msf::DBManager::Loot search_term = opts.delete(:search_term) ::ActiveRecord::Base.connection_pool.with_connection { + # If we have the ID, there is no point in creating a complex query. + if opts[:id] && !opts[:id].to_s.empty? + return Array.wrap(Mdm::Loot.find(opts[:id])) + end + wspace = Msf::Util::DBManager.process_opts_workspace(opts, framework) opts[:workspace_id] = wspace.id diff --git a/lib/msf/core/db_manager/note.rb b/lib/msf/core/db_manager/note.rb index 0c85e243e9..f81bad6852 100644 --- a/lib/msf/core/db_manager/note.rb +++ b/lib/msf/core/db_manager/note.rb @@ -23,6 +23,11 @@ module Msf::DBManager::Note # def notes(opts) ::ActiveRecord::Base.connection_pool.with_connection { + # If we have the ID, there is no point in creating a complex query. + if opts[:id] && !opts[:id].to_s.empty? + return Array.wrap(Mdm::Note.find(opts[:id])) + end + wspace = Msf::Util::DBManager.process_opts_workspace(opts, framework) data = opts.delete(:data) diff --git a/lib/msf/core/db_manager/service.rb b/lib/msf/core/db_manager/service.rb index 64c80d8382..852b72442c 100644 --- a/lib/msf/core/db_manager/service.rb +++ b/lib/msf/core/db_manager/service.rb @@ -143,14 +143,19 @@ module Msf::DBManager::Service # Returns a list of all services in the database def services(opts) - wspace = Msf::Util::DBManager.process_opts_workspace(opts, framework) - search_term = opts.delete(:search_term) order_args = [:port] order_args.unshift(Mdm::Host.arel_table[:address]) if opts.key?(:hosts) ::ActiveRecord::Base.connection_pool.with_connection { + # If we have the ID, there is no point in creating a complex query. + if opts[:id] && !opts[:id].to_s.empty? + return Array.wrap(Mdm::Service.find(opts[:id])) + end + + wspace = Msf::Util::DBManager.process_opts_workspace(opts, framework) + if search_term && !search_term.empty? column_search_conditions = Msf::Util::DBManager.create_all_column_search_conditions(Mdm::Service, search_term) wspace.services.includes(:host).where(opts).where(column_search_conditions).order(*order_args) diff --git a/lib/msf/core/db_manager/session.rb b/lib/msf/core/db_manager/session.rb index b33f8cd8ab..6a48afaf3a 100644 --- a/lib/msf/core/db_manager/session.rb +++ b/lib/msf/core/db_manager/session.rb @@ -8,6 +8,11 @@ module Msf::DBManager::Session return if not active ::ActiveRecord::Base.connection_pool.with_connection { + # If we have the ID, there is no point in creating a complex query. + if opts[:id] && !opts[:id].to_s.empty? + return Array.wrap(Mdm::Session.find(opts[:id])) + end + wspace = Msf::Util::DBManager.process_opts_workspace(opts, framework) search_term = opts.delete(:search_term) diff --git a/lib/msf/core/db_manager/session_event.rb b/lib/msf/core/db_manager/session_event.rb index 8b342ca398..76a1a90f41 100644 --- a/lib/msf/core/db_manager/session_event.rb +++ b/lib/msf/core/db_manager/session_event.rb @@ -2,6 +2,10 @@ module Msf::DBManager::SessionEvent def session_events(opts) ::ActiveRecord::Base.connection_pool.with_connection { + # If we have the ID, there is no point in creating a complex query. + if opts[:id] && !opts[:id].to_s.empty? + return Array.wrap(Mdm::SessionEvent.find(opts[:id])) + end conditions = {} Mdm::SessionEvent.all diff --git a/lib/msf/core/db_manager/vuln.rb b/lib/msf/core/db_manager/vuln.rb index 742c748122..a4dff43b57 100644 --- a/lib/msf/core/db_manager/vuln.rb +++ b/lib/msf/core/db_manager/vuln.rb @@ -236,6 +236,11 @@ module Msf::DBManager::Vuln # def vulns(opts) ::ActiveRecord::Base.connection_pool.with_connection { + # If we have the ID, there is no point in creating a complex query. + if opts[:id] && !opts[:id].to_s.empty? + return Array.wrap(Mdm::Vuln.find(opts[:id])) + end + wspace = Msf::Util::DBManager.process_opts_workspace(opts, framework) search_term = opts.delete(:search_term) diff --git a/lib/msf/core/db_manager/vuln_attempt.rb b/lib/msf/core/db_manager/vuln_attempt.rb index b179b9d46f..1ac7b61dbd 100644 --- a/lib/msf/core/db_manager/vuln_attempt.rb +++ b/lib/msf/core/db_manager/vuln_attempt.rb @@ -23,6 +23,11 @@ module Msf::DBManager::VulnAttempt # def vuln_attempts(opts) ::ActiveRecord::Base.connection_pool.with_connection { + # If we have the ID, there is no point in creating a complex query. + if opts[:id] && !opts[:id].to_s.empty? + return Array.wrap(Mdm::VulnAttempt.find(opts[:id])) + end + # 'workspace' is not a valid attribute for Mdm::VulnAttempt. Remove it. Msf::Util::DBManager.delete_opts_workspace(opts) diff --git a/lib/msf/core/db_manager/workspace.rb b/lib/msf/core/db_manager/workspace.rb index 14f86a575f..1a3117a159 100644 --- a/lib/msf/core/db_manager/workspace.rb +++ b/lib/msf/core/db_manager/workspace.rb @@ -47,6 +47,11 @@ module Msf::DBManager::Workspace def workspaces(opts = {}) ::ActiveRecord::Base.connection_pool.with_connection { + # If we have the ID, there is no point in creating a complex query. + if opts[:id] && !opts[:id].to_s.empty? + return Array.wrap(Mdm::Workspace.find(opts[:id])) + end + search_term = opts.delete(:search_term) # Passing these values to the search will cause exceptions, so remove them if they accidentally got passed in. Msf::Util::DBManager.delete_opts_workspace(opts) diff --git a/lib/msf/ui/console/command_dispatcher/creds.rb b/lib/msf/ui/console/command_dispatcher/creds.rb index 5de52e2f3a..a38ab83317 100644 --- a/lib/msf/ui/console/command_dispatcher/creds.rb +++ b/lib/msf/ui/console/command_dispatcher/creds.rb @@ -412,10 +412,10 @@ class Creds origin = '' if core.origin.kind_of?(Metasploit::Credential::Origin::Service) - service = framework.db.services(id: core.origin.service_id, workspace: framework.db.workspace).first + service = framework.db.services(id: core.origin.service_id).first origin = service.host.address elsif core.origin.kind_of?(Metasploit::Credential::Origin::Session) - session = framework.db.sessions(id: core.origin.session_id, workspace: framework.db.workspace).first + session = framework.db.sessions(id: core.origin.session_id).first origin = session.host.address end @@ -443,8 +443,7 @@ class Creds ] else core.logins.each do |login| - - service = framework.db.services(id: login.service_id, workspace: framework.db.workspace).first + service = framework.db.services(id: login.service_id).first # If none of this Core's associated Logins is for a host within # the user-supplied RangeWalker, then we don't have any reason to # print it out. However, we treat the absence of ranges as meaning