Skip to content

Commit

Permalink
Merge pull request #56 from yashviagrawal/develop
Browse files Browse the repository at this point in the history
DAST
  • Loading branch information
ginilpg authored Feb 11, 2025
2 parents 6df9536 + 302f362 commit 50223b4
Show file tree
Hide file tree
Showing 14 changed files with 1,036 additions and 83 deletions.
1 change: 1 addition & 0 deletions appknox/analyses.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ type Finding struct {
// AnalysisListOptions specifies the optional parameters to the
// AnalysesService.List method.
type AnalysisListOptions struct {
VulnerabilityType int `url:"vulnerability_type,omitempty"`
ListOptions
}

Expand Down
4 changes: 4 additions & 0 deletions appknox/appknox.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ type Client struct {

// Reports service is used to interact with appknox reports api.
Reports *ReportsService

// Dynamic Scan service is used to interact with appknox DAST related APIs
DynamicScans *DynamicScanService
}

// NewClient returns a new appknox API client.
Expand Down Expand Up @@ -102,6 +105,7 @@ func NewClient(accessToken string) (*Client, error) {
c.OWASP = (*OWASPService)(&c.common)
c.Organizations = (*OrganizationsService)(&c.common)
c.Reports = (*ReportsService)(&c.common)
c.DynamicScans = (*DynamicScanService)(&c.common)
return c, nil
}

Expand Down
121 changes: 121 additions & 0 deletions appknox/dynamic_scans.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package appknox

import (
"context"
"fmt"
"net/http"
"time"

"github.com/appknox/appknox-go/appknox/enums"
)

// DynamicScanService handles communication with the DAST related methods
type DynamicScanService service

// DRFResponseDynamicScan represents the DRF response for the Appknox dynamic scan API.
type DRFResponseDynamicScan struct {
Count int `json:"count,omitempty"`
Next string `json:"next,omitempty"`
Previous string `json:"previous,omitempty"`
Results []*DynamicScan `json:"results"`
}

// DynamicScanResponse is a wrapper around DRFResponseDynamicScan
// that can help with further pagination if needed.
type DynamicScanResponse struct {
r *DRFResponseDynamicScan
s *DynamicScanService
c *context.Context
}

// DynamicScanListOptions is similar to AnalysisListOptions,
// letting us specify limit, offset, etc.
type DynamicScanListOptions struct {
ListOptions // from appknox.go
}

// DynamicScan represents a single dynamic scan object (DAST) in Appknox.
type DynamicScan struct {
ID int `json:"id,omitempty"`
File int `json:"file,omitempty"`
PackageName string `json:"package_name,omitempty"`
Mode enums.DynamicScanModeType `json:"mode,omitempty"`
ModeDisplay string `json:"mode_display,omitempty"`
Status enums.DynamicScanStatusType `json:"status,omitempty"`
StatusDisplay string `json:"status_display,omitempty"`
MoriartyDynamicScanRequestID string `json:"moriarty_dynamicscanrequest_id,omitempty"`
EnableAPICapture bool `json:"enable_api_capture,omitempty"`
MoriartyDynamicScanID string `json:"moriarty_dynamicscan_id,omitempty"`
MoriartyDynamicScanToken string `json:"moriarty_dynamicscan_token,omitempty"`
StartedByUser int `json:"started_by_user,omitempty"`
StoppedByUser int `json:"stopped_by_user,omitempty"`
DeviceUsed map[string]interface{} `json:"device_used,omitempty"`
DevicePreference map[string]interface{} `json:"device_preference,omitempty"`
ErrorCode string `json:"error_code,omitempty"`
ErrorMessage string `json:"error_message,omitempty"`
CreatedOn *time.Time `json:"created_on,omitempty"`
UpdatedOn *time.Time `json:"updated_on,omitempty"`
EndedOn *time.Time `json:"ended_on,omitempty"`
AutoShutDownOn *time.Time `json:"auto_shutdown_on,omitempty"`
IsAnalysisDone bool `json:"is_analysis_done,omitempty"`
}

// ListByFile lists the dynamic scans for a given file ID.
func (s *DynamicScanService) ListByFile(
ctx context.Context,
fileID int,
opt *DynamicScanListOptions,
) ([]*DynamicScan, *DynamicScanResponse, error) {

// Base endpoint: e.g. "api/v2/files/123/dynamicscans"
baseEndpoint := fmt.Sprintf("api/v2/files/%v/dynamicscans", fileID)

// If user wants limit=1 (or any other limit), we apply it here
finalURL, err := addOptions(baseEndpoint, opt)
if err != nil {
return nil, nil, err
}

req, err := s.client.NewRequest(http.MethodGet, finalURL, nil)
if err != nil {
return nil, nil, err
}

var drfResponse DRFResponseDynamicScan
_, err = s.client.Do(ctx, req, &drfResponse)
if err != nil {
return nil, nil, err
}
resp := DynamicScanResponse{
r: &drfResponse,
s: s,
c: &ctx,
}
return drfResponse.Results, &resp, nil
}

// ScheduleDastAutomation sends a POST request to schedule a DAST automation
// for the specified file ID.
func (s *DynamicScanService) ScheduleDastAutomation(ctx context.Context, fileID int, mode int,) (*Response, error) {

// The payload for the POST
payload := struct {
Mode int `json:"mode"`
}{
Mode: mode,
}

// POST /api/v2/files/<file_id>/dynamicscans
endpoint := fmt.Sprintf("api/v2/files/%d/dynamicscans", fileID)

req, err := s.client.NewRequest(http.MethodPost, endpoint, payload)
if err != nil {
return nil, err
}

resp, err := s.client.Do(ctx, req, nil)
if err != nil {
return nil, err
}
return resp, nil
}
33 changes: 33 additions & 0 deletions appknox/enums/dynamicScanMode.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package enums

// DynamicScanModeType represents the mode in which a dynamic scan can run.
type DynamicScanModeType int

const (
dynamicScanModeManual DynamicScanModeType = 0
dynamicScanModeAutomated DynamicScanModeType = 1
)

// dynamicScanModeStruct holds references to each dynamic scan mode
// and a map from code => human-readable string.
type dynamicScanModeStruct struct {
Manual DynamicScanModeType
Automated DynamicScanModeType
mappingHumanize map[DynamicScanModeType]string
}

// DynamicScanMode provides the enumerations and the human-readable strings
// for Appknox dynamic scan modes (manual or automated).
var DynamicScanMode = dynamicScanModeStruct{
Manual: dynamicScanModeManual,
Automated: dynamicScanModeAutomated,
mappingHumanize: map[DynamicScanModeType]string{
dynamicScanModeManual: "Manual",
dynamicScanModeAutomated: "Automated",
},
}

// String returns the human-readable name for a given DynamicScanModeType.
func (d DynamicScanModeType) String() string {
return DynamicScanMode.mappingHumanize[d]
}
48 changes: 28 additions & 20 deletions appknox/enums/dynamicScanState.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,51 +4,59 @@ package enums
type DynamicScanStateType int

const (
dynamicScanStateUnknown DynamicScanStateType = -1
dynamicScanStateError DynamicScanStateType = -1
dynamicScanStateNone DynamicScanStateType = 0
dynamicScanStateBooting DynamicScanStateType = 1
dynamicScanStateReady DynamicScanStateType = 2
dynamicScanStateShuttingDown DynamicScanStateType = 3
dynamicScanStateDownloading DynamicScanStateType = 4
dynamicScanStateInstalling DynamicScanStateType = 5
dynamicScanStateLaunching DynamicScanStateType = 6
dynamicScanStateHooking DynamicScanStateType = 7
dynamicScanStateInQueue DynamicScanStateType = 1
dynamicScanStateBooting DynamicScanStateType = 2
dynamicScanStateDownloading DynamicScanStateType = 3
dynamicScanStateInstalling DynamicScanStateType = 4
dynamicScanStateLaunching DynamicScanStateType = 5
dynamicScanStateHooking DynamicScanStateType = 6
dynamicScanStateReady DynamicScanStateType = 7
dynamicScanStateShuttingDown DynamicScanStateType = 8
dynamicScanStateCompleted DynamicScanStateType = 9
)

type dynamicScanStateStruct struct {
Unknown DynamicScanStateType
Error DynamicScanStateType
None DynamicScanStateType
InQueue DynamicScanStateType
Booting DynamicScanStateType
Ready DynamicScanStateType
ShuttingDown DynamicScanStateType
Downloading DynamicScanStateType
Installing DynamicScanStateType
Launching DynamicScanStateType
Hooking DynamicScanStateType
Ready DynamicScanStateType
ShuttingDown DynamicScanStateType
Completed DynamicScanStateType
mappingHumanize map[DynamicScanStateType]string
}

// DynamicScanState represents the dynamic scan status
var DynamicScanState = dynamicScanStateStruct{
Unknown: dynamicScanStateUnknown,
Error: dynamicScanStateError,
None: dynamicScanStateNone,
InQueue: dynamicScanStateInQueue,
Booting: dynamicScanStateBooting,
Ready: dynamicScanStateReady,
ShuttingDown: dynamicScanStateShuttingDown,
Downloading: dynamicScanStateDownloading,
Installing: dynamicScanStateInstalling,
Launching: dynamicScanStateLaunching,
Hooking: dynamicScanStateHooking,
Ready: dynamicScanStateReady,
ShuttingDown: dynamicScanStateShuttingDown,
Completed: dynamicScanStateCompleted,
mappingHumanize: map[DynamicScanStateType]string{
dynamicScanStateUnknown: "Unknown",
dynamicScanStateError: "Error",
dynamicScanStateNone: "None",
dynamicScanStateInQueue: "In Queue",
dynamicScanStateBooting: "Booting",
dynamicScanStateReady: "Ready",
dynamicScanStateShuttingDown: "ShuttingDown",
dynamicScanStateDownloading: "Downloading",
dynamicScanStateInstalling: "Installing",
dynamicScanStateLaunching: "Launching",
dynamicScanStateDownloading: "Downloading Package",
dynamicScanStateInstalling: "Installing Package",
dynamicScanStateLaunching: "Launching App",
dynamicScanStateHooking: "Hooking",
dynamicScanStateReady: "Ready",
dynamicScanStateShuttingDown: "Shutting Down",
dynamicScanStateCompleted: "Completed",
},
}

Expand Down
137 changes: 137 additions & 0 deletions appknox/enums/dynamicScanStatus.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package enums

// DynamicScanStatusType represents the status codes that a dynamic scan can have.
type DynamicScanStatusType int

// These constants list all possible dynamic scan statuses recognized by Appknox.
const (
dynamicScanStatusNotStarted DynamicScanStatusType = 0
dynamicScanStatusPreProcessing DynamicScanStatusType = 1
dynamicScanStatusProcessingScanRequest DynamicScanStatusType = 2
dynamicScanStatusInQueue DynamicScanStatusType = 3
dynamicScanStatusDeviceAllocated DynamicScanStatusType = 4
dynamicScanStatusConnectingToDevice DynamicScanStatusType = 5
dynamicScanStatusPreparingDevice DynamicScanStatusType = 6
dynamicScanStatusInstalling DynamicScanStatusType = 7
dynamicScanStatusConfiguringAPICapture DynamicScanStatusType = 8
dynamicScanStatusHooking DynamicScanStatusType = 9
dynamicScanStatusLaunching DynamicScanStatusType = 10
dynamicScanStatusReadyForInteraction DynamicScanStatusType = 11
dynamicScanStatusDownloadingAutoPilotScript DynamicScanStatusType = 12
dynamicScanStatusConfiguringAutoPilot DynamicScanStatusType = 13
dynamicScanStatusAutoPilotRunning DynamicScanStatusType = 14
dynamicScanStatusAutoPilotCompleted DynamicScanStatusType = 15
dynamicScanStatusStopScanRequested DynamicScanStatusType = 16
dynamicScanStatusScanTimeLimitExceeded DynamicScanStatusType = 17
dynamicScanStatusShuttingDown DynamicScanStatusType = 18
dynamicScanStatusCleaningDevice DynamicScanStatusType = 19
dynamicScanStatusRuntimeDetectionCompleted DynamicScanStatusType = 20
dynamicScanStatusAnalyzing DynamicScanStatusType = 21
dynamicScanStatusAnalysisCompleted DynamicScanStatusType = 22
dynamicScanStatusTimedOut DynamicScanStatusType = 23
dynamicScanStatusError DynamicScanStatusType = 24
dynamicScanStatusCancelled DynamicScanStatusType = 25
dynamicScanStatusTerminated DynamicScanStatusType = 26
)

// dynamicScanStatusStruct holds references to each of the status codes
// and a map from code => human-readable string.
type dynamicScanStatusStruct struct {
NotStarted DynamicScanStatusType
PreProcessing DynamicScanStatusType
ProcessingScanRequest DynamicScanStatusType
InQueue DynamicScanStatusType
DeviceAllocated DynamicScanStatusType
ConnectingToDevice DynamicScanStatusType
PreparingDevice DynamicScanStatusType
Installing DynamicScanStatusType
ConfiguringAPICapture DynamicScanStatusType
Hooking DynamicScanStatusType
Launching DynamicScanStatusType
ReadyForInteraction DynamicScanStatusType
DownloadingAutoPilotScript DynamicScanStatusType
ConfiguringAutoPilot DynamicScanStatusType
AutoPilotRunning DynamicScanStatusType
AutoPilotCompleted DynamicScanStatusType
StopScanRequested DynamicScanStatusType
ScanTimeLimitExceeded DynamicScanStatusType
ShuttingDown DynamicScanStatusType
CleaningDevice DynamicScanStatusType
RuntimeDetectionCompleted DynamicScanStatusType
Analyzing DynamicScanStatusType
AnalysisCompleted DynamicScanStatusType
TimedOut DynamicScanStatusType
Error DynamicScanStatusType
Cancelled DynamicScanStatusType
Terminated DynamicScanStatusType

// mappingHumanize maps each status code to a human-readable string.
mappingHumanize map[DynamicScanStatusType]string
}

// DynamicScanStatus exports the enumerations and the human-readable strings
// for Appknox dynamic scan statuses.
var DynamicScanStatus = dynamicScanStatusStruct{
NotStarted: dynamicScanStatusNotStarted,
PreProcessing: dynamicScanStatusPreProcessing,
ProcessingScanRequest: dynamicScanStatusProcessingScanRequest,
InQueue: dynamicScanStatusInQueue,
DeviceAllocated: dynamicScanStatusDeviceAllocated,
ConnectingToDevice: dynamicScanStatusConnectingToDevice,
PreparingDevice: dynamicScanStatusPreparingDevice,
Installing: dynamicScanStatusInstalling,
ConfiguringAPICapture: dynamicScanStatusConfiguringAPICapture,
Hooking: dynamicScanStatusHooking,
Launching: dynamicScanStatusLaunching,
ReadyForInteraction: dynamicScanStatusReadyForInteraction,
DownloadingAutoPilotScript: dynamicScanStatusDownloadingAutoPilotScript,
ConfiguringAutoPilot: dynamicScanStatusConfiguringAutoPilot,
AutoPilotRunning: dynamicScanStatusAutoPilotRunning,
AutoPilotCompleted: dynamicScanStatusAutoPilotCompleted,
StopScanRequested: dynamicScanStatusStopScanRequested,
ScanTimeLimitExceeded: dynamicScanStatusScanTimeLimitExceeded,
ShuttingDown: dynamicScanStatusShuttingDown,
CleaningDevice: dynamicScanStatusCleaningDevice,
RuntimeDetectionCompleted: dynamicScanStatusRuntimeDetectionCompleted,
Analyzing: dynamicScanStatusAnalyzing,
AnalysisCompleted: dynamicScanStatusAnalysisCompleted,
TimedOut: dynamicScanStatusTimedOut,
Error: dynamicScanStatusError,
Cancelled: dynamicScanStatusCancelled,
Terminated: dynamicScanStatusTerminated,

mappingHumanize: map[DynamicScanStatusType]string{
dynamicScanStatusNotStarted: "Not Started",
dynamicScanStatusPreProcessing: "Preprocessing",
dynamicScanStatusProcessingScanRequest: "Processing scan request",
dynamicScanStatusInQueue: "In Queue",
dynamicScanStatusDeviceAllocated: "Device allocated",
dynamicScanStatusConnectingToDevice: "Connecting to device",
dynamicScanStatusPreparingDevice: "Preparing device",
dynamicScanStatusInstalling: "Installing app",
dynamicScanStatusConfiguringAPICapture: "Preparing for API capture",
dynamicScanStatusHooking: "Preparing for data capture",
dynamicScanStatusLaunching: "Launching app",
dynamicScanStatusReadyForInteraction: "Ready for interaction",
dynamicScanStatusDownloadingAutoPilotScript: "Downloading autopilot script",
dynamicScanStatusConfiguringAutoPilot: "Configuring autopilot",
dynamicScanStatusAutoPilotRunning: "Autopilot running",
dynamicScanStatusAutoPilotCompleted: "Autopilot completed",
dynamicScanStatusStopScanRequested: "Stop scan requested",
dynamicScanStatusScanTimeLimitExceeded: "Scan time limit exceeded",
dynamicScanStatusShuttingDown: "Shutting down",
dynamicScanStatusCleaningDevice: "Cleaning device",
dynamicScanStatusRuntimeDetectionCompleted: "Runtime detection completed",
dynamicScanStatusAnalyzing: "Analyzing",
dynamicScanStatusAnalysisCompleted: "Analysis completed",
dynamicScanStatusTimedOut: "Timed out",
dynamicScanStatusError: "Error",
dynamicScanStatusCancelled: "Cancelled",
dynamicScanStatusTerminated: "Terminated",
},
}

// String returns the human-readable name for a given DynamicScanStatusType.
func (d DynamicScanStatusType) String() string {
return DynamicScanStatus.mappingHumanize[d]
}
Loading

0 comments on commit 50223b4

Please sign in to comment.