ca0e1ca769
This is an initial import of the osel codebase. The osel tool is a tool that initiates external security scans (initially through Qualys) upon reciept of AMQP events that indicate certain sensitive events have occurred, like a security group rule change. The commit history had to be thrown away because it contained some non-public data, so I would like to call out the following contributors: This uses go 1.10 and vgo for dependency management. Co-Authored-By: Charles Bitter <Charles_Bitter@cable.comcast.com> Co-Authored-By: Olivier Gagnon <Olivier_Gagnon@cable.comcast.com> Co-Authored-By: Joseph Sleiman <Joseph_Sleiman@comcast.com> Change-Id: Ib6abe2024fd91978b783ceee4cff8bb4678d7b15
105 lines
3.4 KiB
Go
105 lines
3.4 KiB
Go
package main
|
|
|
|
/*
|
|
|
|
qualys - This file includes all of the logic necessary to interact with the
|
|
go-qualys library. This is extrapolated out so that a QualysInterface
|
|
interface can be passed to functions. Doing this allows testing by mock
|
|
classes to be created that can be passed to functions.
|
|
|
|
Since this is a wrapper around the go-qualys library, this does not need
|
|
testing.
|
|
|
|
*/
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"net/url"
|
|
|
|
"git.openstack.org/openstack/osel/qualys"
|
|
)
|
|
|
|
// QualysActioner is an interface for an QualysActions class. Having
|
|
// this as an interface allows us to pass in a dummy class for testing that
|
|
// just returns mocked data.
|
|
type QualysActioner interface {
|
|
InitiateScan([]string) (string, error)
|
|
DropIPv6() bool
|
|
}
|
|
|
|
// QualysActions is a class that handles all interactions directly with Qualys.
|
|
// See the comment on QualysActioner for rationale.
|
|
type QualysActions struct {
|
|
Options QualysOptions
|
|
}
|
|
|
|
// QualysOptions is a class to convey all of the configurable options for the
|
|
// QualysActions class.
|
|
type QualysOptions struct {
|
|
DropIPv6 bool
|
|
MinRemaining int
|
|
ProxyURL *url.URL
|
|
Password string
|
|
QualysURL *url.URL
|
|
ScanOptionName string
|
|
UserName string
|
|
}
|
|
|
|
// InitiateScan is the main method for the QualysActioner class, it
|
|
// makes a call to the Qualys API to start a scan and harvests a scan ID, and
|
|
// an optional error string if there is a problem contacting Qualys.
|
|
func (s *QualysActions) InitiateScan(targetIPAddresses []string) (string, error) {
|
|
var err error
|
|
|
|
// create client with proxy so the qualys service can be accessed
|
|
qualysCreds := qualys.Credentials{
|
|
Username: s.Options.UserName,
|
|
Password: s.Options.Password,
|
|
}
|
|
c, err := qualys.NewClient(&http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(s.Options.ProxyURL)}}, &qualysCreds)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
c.BaseURL = s.Options.QualysURL
|
|
|
|
// create the options
|
|
opts := qualys.LaunchScanOptions{
|
|
ScanTitle: "osel",
|
|
ScannerName: "External",
|
|
OptionTitle: s.Options.ScanOptionName,
|
|
IP: targetIPAddresses,
|
|
}
|
|
|
|
// launch the request
|
|
launchScanResponse, err := c.LaunchScan(&opts)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// process the request response
|
|
scanID := launchScanResponse.ScanReference
|
|
remainingQualysRequests := launchScanResponse.RateLimitations.Remaining
|
|
allowedQualysRequests := launchScanResponse.RateLimitations.Limit
|
|
if Debug {
|
|
log.Printf("Qualys Rate Limit: %d of %d total requests remaining, concurrency of %d out of %d, %d seconds remaining in limit window and %d seconds until a request can be made again\n",
|
|
remainingQualysRequests, allowedQualysRequests, launchScanResponse.RateLimitations.CurrentConcurrency,
|
|
launchScanResponse.RateLimitations.ConcurrencyLimit, launchScanResponse.RateLimitations.LimitWindow, launchScanResponse.RateLimitations.WaitingPeriod)
|
|
}
|
|
if launchScanResponse.Text != "" {
|
|
err = errors.New(launchScanResponse.Text)
|
|
}
|
|
if remainingQualysRequests <= s.Options.MinRemaining {
|
|
err = fmt.Errorf("halting Qualys processing! Only %d Qualys calls remain out of a total of %d. Waiting for %d seconds before resuming", remainingQualysRequests,
|
|
allowedQualysRequests, launchScanResponse.RateLimitations.LimitWindow)
|
|
}
|
|
return scanID, err
|
|
}
|
|
|
|
// DropIPv6 is an accessor method to allow other code to make decisions based on whether this flag is enabled.
|
|
func (s *QualysActions) DropIPv6() bool {
|
|
return s.Options.DropIPv6
|
|
}
|