Module: Arachni::RPC::Server::Framework::Master

Included in:
MultiInstance
Defined in:
lib/arachni/rpc/server/framework/master.rb

Overview

Holds methods for master Instances, both for remote management and utility ones.

Author:

Instance Method Summary collapse

Instance Method Details

#enslave(instance_info, opts = {}, &block) ⇒ Bool

Enslaves another instance and subsequently becomes the master of the group.

Parameters:

  • instance_info (Hash)

    ‘{ ’url’ => ‘<host>:<port>’, ‘token’ => ‘s3cr3t’ }‘

Returns:

  • (Bool)

    ‘true` on success, `false` is this instance is a slave (slaves can’t have slaves of their own).



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/arachni/rpc/server/framework/master.rb', line 82

def enslave( instance_info, opts = {}, &block )
    # Slaves can't have slaves of their own.
    if slave?
        block.call false
        return false
    end

    instance_info = instance_info.symbolize_keys

    fail "Instance info does not contain a 'url' key."   if !instance_info[:url]
    fail "Instance info does not contain a 'token' key." if !instance_info[:token]

    # Since we have slaves we must be a master.
    set_as_master

    # Take charge of the Instance we were given.
    instance = connect_to_instance( instance_info )
    instance.opts.set( cleaned_up_opts ) do
        instance.framework.set_master( multi_self_url, token ) do
            @instances << instance_info

            print_status "Enslaved: #{instance_info[:url]}"

            block.call true if block_given?
        end
    end

    true
end

#master?Bool

Returns ‘true` if running in HPG (High Performance Grid) mode and instance is the master, false otherwise.

Returns:

  • (Bool)

    ‘true` if running in HPG (High Performance Grid) mode and instance is the master, false otherwise.



67
68
69
70
# File 'lib/arachni/rpc/server/framework/master.rb', line 67

def master?
    # Only master needs a local token.
    !!@local_token
end

#set_as_masterBool

Sets this instance as the master.

Returns:

  • (Bool)

    ‘true` on success, `false` if this instance is not a solo one.



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/arachni/rpc/server/framework/master.rb', line 33

def set_as_master
    return false if !solo?
    return true if master?

    # Holds info for our slave Instances -- if we have any.
    @instances        = []

    # Instances which have been distributed some scan workload.
    @running_slaves   = Set.new

    # Instances which have completed their scan.
    @done_slaves      = Set.new

    # Holds element IDs for each page, to be used as a representation of the
    # the audit workload that will need to be distributed.
    @element_ids_per_url = {}

    # Some methods need to be accessible over RPC for instance management,
    # restricting elements, adding more pages etc.
    #
    # However, when in multi-Instance mode, the master should not be tampered
    # with, so we generate a local token (which is not known to regular API clients)
    # to be used server side by self to facilitate access control and only
    # allow slaves to update our runtime data.
    @local_token = Utilities.generate_token

    print_status 'Became master.'

    true
end

#slave_done(slave_url, token = nil) ⇒ Bool

Signals that a slave has finished auditing – each slave must call this when it finishes its job.

Parameters:

  • slave_url (String)

    URL of the calling slave.

  • token (String) (defaults to: nil)

    Privileged token, prevents this method from being called by 3rd parties when this instance is a master. If this instance is not a master one the token needn’t be provided.

Returns:

  • (Bool)

    ‘true` on success, `false` on invalid `token`.



126
127
128
129
130
131
132
133
134
# File 'lib/arachni/rpc/server/framework/master.rb', line 126

def slave_done( slave_url, token = nil )
    return false if master? && !valid_token?( token )
    @done_slaves << slave_url

    print_status "Slave done: #{slave_url}"

    cleanup_if_all_done
    true
end

#slave_sitrep(data, url, token = nil) ⇒ Bool

Used by slaves to impart the knowledge they’ve gained during the scan to the master as well as for signaling.

Parameters:

  • data (Hash)
  • url (String)

    URL of the slave.

  • token (String) (defaults to: nil)

    Privileged token, prevents this method from being called by 3rd parties when this instance is a master. If this instance is not a master one the token needn’t be provided.

Options Hash (data):

Returns:

  • (Bool)

    ‘true` on success, `false` on invalid `token`.



213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/arachni/rpc/server/framework/master.rb', line 213

def slave_sitrep( data, url, token = nil )
    return false if master? && !valid_token?( token )

    update_element_ids_per_url( data[:element_ids_per_url] || {}, token )
    update_issues( data[:issues] || [], token )

    Platform::Manager.update_light( data[:platforms] || {} ) if Options.fingerprint?

    spider.peer_done( url ) if data[:crawl_done]
    slave_done( url, token ) if data[:audit_done]

    true
end

#update_element_ids_per_url(element_ids_per_url = {}, token = nil) ⇒ Bool

Used by slave crawlers to update the master’s list of element IDs per URL.

Parameters:

  • element_ids_per_url (Hash) (defaults to: {})

    List of element IDs (as created by Element::Capabilities::Auditable#scope_audit_id) for each page (by URL).

  • token (String) (defaults to: nil)

    Privileged token, prevents this method from being called by 3rd parties when this instance is a master. If this instance is not a master one the token needn’t be provided.

Returns:

  • (Bool)

    ‘true` on success, `false` on invalid `token`.



174
175
176
177
178
179
180
181
182
183
# File 'lib/arachni/rpc/server/framework/master.rb', line 174

def update_element_ids_per_url( element_ids_per_url = {}, token = nil )
    return false if master? && !valid_token?( token )

    element_ids_per_url.each do |url, ids|
        @element_ids_per_url[url] ||= []
        @element_ids_per_url[url] |= ids
    end

    true
end

#update_issues(issues, token = nil) ⇒ Bool

Registers an array holding Issue objects with the local instance.

Used by slaves to register the issues they find.

Parameters:

  • issues (Array<Arachni::Issue>)
  • token (String) (defaults to: nil)

    Privileged token, prevents this method from being called by 3rd parties when this instance is a master. If this instance is not a master one the token needn’t be provided.

Returns:

  • (Bool)

    ‘true` on success, `false` on invalid `token`.



151
152
153
154
155
# File 'lib/arachni/rpc/server/framework/master.rb', line 151

def update_issues( issues, token = nil )
    return false if master? && !valid_token?( token )
    @modules.class.register_results( issues )
    true
end