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:

  • Tasos “Zapotek” Laskos <tasos.laskos@arachni-scanner.com>

Instance Method Summary collapse

Instance Method Details

#enslave(instance_info, &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).



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/arachni/rpc/server/framework/master.rb', line 65

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

    instance_info = instance_info.my_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.options.set( prepare_slave_options ) do
        instance.framework.set_master( multi_self_url, token ) do
            @slaves << instance_info

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

            block.call true if block_given?
        end
    end

    true
end

#has_slaves?Boolean

Returns:

  • (Boolean)


45
46
47
# File 'lib/arachni/rpc/server/framework/master.rb', line 45

def has_slaves?
    @slaves && @slaves.any?
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.



52
53
54
55
# File 'lib/arachni/rpc/server/framework/master.rb', line 52

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.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/arachni/rpc/server/framework/master.rb', line 21

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

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

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

    # 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_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):

  • :audit_done (Boolean)

    `true` if the slave has finished auditing, `false` otherwise.

  • :issues (Array<Arachni::Issue>)

Returns:

  • (Bool)

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



113
114
115
116
117
118
119
120
121
# File 'lib/arachni/rpc/server/framework/master.rb', line 113

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

    issues = (data['issues'] || []).map { |i| Arachni::Issue.from_rpc_data i }
    update_issues( issues )
    slave_done( url ) if data['audit_done']

    true
end