-
Notifications
You must be signed in to change notification settings - Fork 103
Using Nexpose::Wait
The Nexpose::Wait class is meant to be an easy way to add a few lines to your scripts in order to make sure certain actions have completed prior to moving on to the next steps within your task. It has built in methods for common actions, and a custom option for more specific needs.
The Nexpose::Wait uses the keyword arguments feature in the Ruby language for calling a method, so it might look a bit odd at first, but using keyword arguments should be more convenient overall.
wait = Nexpose::Wait.new(retry_count: 5, timeout: 60, polling_interval: 5)
At this point you've instantiated a new Wait object which will try to evaluate every five seconds, for a total of 300 seconds (60 second timeout, retrying five total times - 60 seconds multiplied by 5).
Since we are using keyword arguments, you can initialize retry_count
, timeout
and polling_interval
in any order. And if you want to use just the default values, you do not need to include any arguments.
The following code uses just the default values.
wait = Nexpose::Wait.new
Default Values:
-
retry_count
0 -
timeout
120 seconds -
polling_interval
1 second
There are now three methods which are available:
wait.for_report
wait.for_integration
wait.for_judgment
wait.for_report
will allow you to wait for a report to finish, and allow you to act once the timeout has been reached. Similar to how you initialized the object, all the methods also use Ruby's keyword arguments.
wait.for_report(nexpose_connection: nsc, report_id: 1)
This will use the wait
we initialized above, and we pass in our nsc connection object, and the ID of the report we want to wait on. This will wait for the report status to 'Generated'.
wait.for_integration
will allow you to wait for a scan to be at a certain state before moving on.
wait.for_integration(nexpose_connection: nsc, scan_id: 1, status: 'finished')
Common statuses would be finished
, stopped
, running
, integrating
or paused
. Whichever status our heart desires we can just have the wait.for_integration
keep asking Nexpose the status of that particular scan.
wait.for_judgment
is a bit of a wildcard, because instead of the method looking for something Nexpose specific, we can have this wait do whatever we need. One example might be, we have kicked off a few small scans and we want to wait for them all to finish.
wait.for_judgment( proc: -> { nsc.activity.empty?}, desc: "Waiting for All Scan Activity to be Complete")
For this method, we create a proc that uses the nsc.activity
method to tell us if any scans are running. The proc can literally be any condition that we want to wait until is true.
wait.for_judgment( proc: -> {1 == 1}, desc: "Waiting for one to equal one...")
Above is a silly example, but it's to show that we do not need to use a Nexpose function inside of our wait.for_judgment
method. Another example might be you have another tool running along side your script, and you would like to wait for an action within that tool to finish prior to doing something within Nexpose.
wait.for_judgment( proc: -> {Tool::Status == 'Ready'}, desc: "Waiting for external tool to finish.")
We use the desc:
argument to tell us what this judgment is judging. This will be more clear when we look at getting the error message when our wait fails.
Now that we've setup our wait
how do we know that it actually worked?
We can know if the wait
finished without error, by using wait.ready?
. Also the error message is available with the type of error that was encountered, wait.error_message
. Note: wait.error_message
always has a value, and you should only rely on wait.ready?
to know if your wait
successfully completed. A common full example is shown below.
wait = Nexpose::Wait.new(retry_count: 5, timeout: 60, polling_interval: 5)
wait.for_report(nexpose_connection: nsc, report_id: 1)
raise wait.error_message unless wait.ready?
The Nexpose::Wait class has the ability for the same instance of the object to be reused. This might be helpful if you want to define one global set of default timeouts and polling intervals, without having to instantiate a new wait object. For example, if you have a script that will generate a bunch of reports, and you want to wait for all of them, you do not necessarily need to re-instantiate your wait
.
wait = Nexpose::Wait.new(retry_count: 5, timeout: 60, polling_interval: 5)
wait.for_report(nexpose_connection: nsc, report_id: 1)
raise wait.error_message unless wait.ready?
wait.for_report(nexpose_connection: nsc, report_id: 2)
raise wait.error_message unless wait.ready?
wait.for_report(nexpose_connection: nsc, report_id: 3)
raise wait.error_message unless wait.ready?
In the above example we just called Nexpose::Wait.new
only once, but we were able to reuse the same object for each of our different report_id
s. We can also reuse the same object and use any of the different .for_
methods with the same result.
wait = Nexpose::Wait.new(retry_count: 5, timeout: 60, polling_interval: 5)
wait.for_report(nexpose_connection: nsc, report_id: 1)
raise wait.error_message unless wait.ready?
wait.for_integration(nexpose_connection: nsc, scan_id: 1, status: 'finished')
raise wait.error_message unless wait.ready?
wait.for_judgment( proc: -> { nsc.activity.empty?}, desc: "Waiting for All Scan Activity to be Complete")
raise wait.error_message unless wait.ready?
Project Home 🔹 Release Notes 🔹 Wiki 🔹 Issues 🔹 Pull Requests