scan

package
v0.1.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 14, 2026 License: GPL-3.0 Imports: 22 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// MaxConcurrentRunsPerScan is the maximum concurrent runs per scan config.
	MaxConcurrentRunsPerScan = 3

	// MaxConcurrentRunsPerTenant is the maximum concurrent runs per tenant.
	MaxConcurrentRunsPerTenant = 50
)

Concurrent run limits for scans.

View Source
const QuickScanTemplateID = "00000000-0000-0000-0000-000000000001"

QuickScanTemplateID is the system template ID for quick/single scans. This template is created during database migration/seed.

Variables

This section is empty.

Functions

This section is empty.

Types

type AgentAvailability

type AgentAvailability struct {
	HasTenantAgent   bool
	HasPlatformAgent bool
	Available        bool
	Message          string
}

AgentAvailability represents agent availability status.

type AgentSelector

type AgentSelector interface {
	CheckAgentAvailability(ctx context.Context, tenantID shared.ID, tool string, tenantOnly bool) *AgentAvailability
	CanUsePlatformAgents(ctx context.Context, tenantID shared.ID) (bool, string)
	SelectAgent(ctx context.Context, req SelectAgentRequest) (*SelectAgentResult, error)
}

AgentSelector interface for agent selection.

type AssetCompatibilityPreview

type AssetCompatibilityPreview struct {
	// Whether fully compatible
	IsFullyCompatible bool `json:"is_fully_compatible"`

	// Compatibility percentage (0-100)
	CompatibilityPercent float64 `json:"compatibility_percent"`

	// Counts by compatibility
	CompatibleCount   int `json:"compatible_count"`
	IncompatibleCount int `json:"incompatible_count"`
	UnclassifiedCount int `json:"unclassified_count"`
	TotalCount        int `json:"total_count"`

	// Details
	CompatibleTypes   []string `json:"compatible_types,omitempty"`
	IncompatibleTypes []string `json:"incompatible_types,omitempty"`

	// Human-readable message
	Message string `json:"message"`
}

AssetCompatibilityPreview represents a compatibility preview at scan creation. This is shown as a warning before the scan is created.

type AssetFilterService

type AssetFilterService struct {
	// contains filtered or unexported fields
}

AssetFilterService handles smart filtering of assets based on tool compatibility.

func NewAssetFilterService

func NewAssetFilterService(
	targetMappingRepo tool.TargetMappingRepository,
	assetGroupRepo assetgroup.Repository,
) *AssetFilterService

NewAssetFilterService creates a new AssetFilterService.

func (*AssetFilterService) FilterAssetsForScan

func (s *AssetFilterService) FilterAssetsForScan(
	ctx context.Context,
	toolTargets []string,
	toolName string,
	assetTypeCounts map[string]int64,
) (*FilteringResult, error)

FilterAssetsForScan filters assets based on tool compatibility. Returns the filtering result showing what was scanned vs skipped.

func (*AssetFilterService) PreviewCompatibility

func (s *AssetFilterService) PreviewCompatibility(
	ctx context.Context,
	toolTargets []string,
	groupIDs []shared.ID,
) (*AssetCompatibilityPreview, error)

PreviewCompatibility checks asset compatibility at scan creation time. Returns a preview showing what percentage of assets will be scanned.

type AuditContext

type AuditContext struct {
	TenantID string
	ActorID  string
}

AuditContext contains context for audit logging.

type AuditEvent

type AuditEvent struct {
	Action       audit.Action
	ResourceType audit.ResourceType
	ResourceID   string
	ResourceName string
	Message      string
	Success      bool
	Error        error
	Metadata     map[string]any
}

AuditEvent represents an audit event.

func NewFailureEvent

func NewFailureEvent(action audit.Action, resourceType audit.ResourceType, resourceID string, err error) AuditEvent

NewFailureEvent creates a failure audit event.

func NewSuccessEvent

func NewSuccessEvent(action audit.Action, resourceType audit.ResourceType, resourceID string) AuditEvent

NewSuccessEvent creates a success audit event.

func (AuditEvent) WithMessage

func (e AuditEvent) WithMessage(msg string) AuditEvent

WithMessage sets the message.

func (AuditEvent) WithMetadata

func (e AuditEvent) WithMetadata(key string, value any) AuditEvent

WithMetadata adds metadata.

func (AuditEvent) WithResourceName

func (e AuditEvent) WithResourceName(name string) AuditEvent

WithResourceName sets the resource name.

type AuditService

type AuditService interface {
	LogEvent(ctx context.Context, actx AuditContext, event AuditEvent) error
}

AuditService interface for audit logging.

type BulkActionResult

type BulkActionResult struct {
	Successful []string `json:"successful"` // IDs that were successfully updated
	Failed     []struct {
		ID    string `json:"id"`
		Error string `json:"error"`
	} `json:"failed"` // IDs that failed with error messages
}

BulkActionResult represents the result of a bulk action.

type CreateScanInput

type CreateScanInput struct {
	TenantID        string         `json:"tenant_id" validate:"required,uuid"`
	Name            string         `json:"name" validate:"required,min=1,max=200"`
	Description     string         `json:"description" validate:"max=1000"`
	AssetGroupID    string         `json:"asset_group_id" validate:"omitempty,uuid"`       // Primary asset group (legacy)
	AssetGroupIDs   []string       `json:"asset_group_ids" validate:"omitempty,dive,uuid"` // Multiple asset groups (NEW)
	Targets         []string       `json:"targets" validate:"omitempty,max=1000"`          // Direct targets
	ScanType        string         `json:"scan_type" validate:"required,oneof=workflow single"`
	PipelineID      string         `json:"pipeline_id" validate:"omitempty,uuid"`
	ScannerName     string         `json:"scanner_name" validate:"max=100"`
	ScannerConfig   map[string]any `json:"scanner_config"`
	TargetsPerJob   int            `json:"targets_per_job"`
	ScheduleType    string         `json:"schedule_type" validate:"omitempty,oneof=manual daily weekly monthly crontab"`
	ScheduleCron    string         `json:"schedule_cron" validate:"max=100"`
	ScheduleDay     *int           `json:"schedule_day"`
	ScheduleTime    *time.Time     `json:"schedule_time"`
	Timezone        string         `json:"timezone" validate:"max=50"`
	Tags            []string       `json:"tags" validate:"max=20,dive,max=50"`
	TenantRunner    bool           `json:"run_on_tenant_runner"`
	AgentPreference string         `json:"agent_preference" validate:"omitempty,oneof=auto tenant platform"` // Agent selection mode: auto (default), tenant, platform
	ProfileID       string         `json:"profile_id" validate:"omitempty,uuid"`                             // Optional scan profile (tool configs, quality gates)
	TimeoutSeconds  int            `json:"timeout_seconds" validate:"omitempty,min=30,max=86400"`            // Max execution time (default 3600, min 30, max 86400)
	// Retry config: max_retries=0 disables retry; backoff is initial delay (exponential per attempt)
	MaxRetries          int    `json:"max_retries" validate:"omitempty,min=0,max=10"`
	RetryBackoffSeconds int    `json:"retry_backoff_seconds" validate:"omitempty,min=10,max=86400"`
	CreatedBy           string `json:"created_by" validate:"omitempty,uuid"`
}

CreateScanInput represents the input for creating a scan. Either AssetGroupID/AssetGroupIDs OR Targets must be provided (can have all).

type CreateScanResult

type CreateScanResult struct {
	Scan                 *scan.Scan                 `json:"scan"`
	CompatibilityWarning *AssetCompatibilityPreview `json:"compatibility_warning,omitempty"`
}

CreateScanResult represents the result of creating a scan. It includes the scan entity and optional compatibility warnings.

type EmbeddedTemplate

type EmbeddedTemplate struct {
	ID           string `json:"id"`
	Name         string `json:"name"`
	TemplateType string `json:"template_type"`
	Content      string `json:"content"`      // Base64 encoded content
	ContentHash  string `json:"content_hash"` // SHA256 hash for verification
}

EmbeddedTemplate represents a template embedded in scan command payload. This is the format sent to agents for custom templates.

type FilteringResult

type FilteringResult struct {
	// Counts
	TotalAssets        int `json:"total_assets"`
	ScannedAssets      int `json:"scanned_assets"`
	SkippedAssets      int `json:"skipped_assets"`
	UnclassifiedAssets int `json:"unclassified_assets"`

	// Compatibility percentage (0-100)
	CompatibilityPercent float64 `json:"compatibility_percent"`

	// Details by asset type
	ScannedByType map[string]int `json:"scanned_by_type,omitempty"`
	SkippedByType map[string]int `json:"skipped_by_type,omitempty"`

	// Reasons for skipping (for UI display)
	SkipReasons []SkipReason `json:"skip_reasons,omitempty"`

	// Whether any filtering occurred
	WasFiltered bool `json:"was_filtered"`

	// Tool info for context
	ToolName         string   `json:"tool_name,omitempty"`
	SupportedTargets []string `json:"supported_targets,omitempty"`
}

FilteringResult represents the result of smart filtering during scan trigger. It shows which assets were scanned vs skipped and why.

type ListScansInput

type ListScansInput struct {
	TenantID     string   `json:"tenant_id" validate:"required,uuid"`
	AssetGroupID string   `json:"asset_group_id" validate:"omitempty,uuid"`
	PipelineID   string   `json:"pipeline_id" validate:"omitempty,uuid"`
	ScanType     string   `json:"scan_type" validate:"omitempty,oneof=workflow single"`
	ScheduleType string   `json:"schedule_type" validate:"omitempty,oneof=manual daily weekly monthly crontab"`
	Status       string   `json:"status" validate:"omitempty,oneof=active paused disabled"`
	Tags         []string `json:"tags"`
	Search       string   `json:"search" validate:"max=255"`
	Page         int      `json:"page"`
	PerPage      int      `json:"per_page"`
}

ListScansInput represents the input for listing scans.

type OverviewStats

type OverviewStats struct {
	Pipelines StatusCounts `json:"pipelines"`
	Scans     StatusCounts `json:"scans"`
	Jobs      StatusCounts `json:"jobs"`
}

OverviewStats represents aggregated statistics for scan management overview.

type QuickScanInput

type QuickScanInput struct {
	TenantID    string         `json:"tenant_id" validate:"required,uuid"`
	Targets     []string       `json:"targets" validate:"required,min=1,max=1000"`
	ScannerName string         `json:"scanner_name" validate:"omitempty,max=100"`
	WorkflowID  string         `json:"workflow_id" validate:"omitempty,uuid"`
	Config      map[string]any `json:"config"`
	Tags        []string       `json:"tags" validate:"max=20,dive,max=50"`
	CreatedBy   string         `json:"created_by" validate:"omitempty,uuid"`
}

QuickScanInput represents the input for quick scan.

type QuickScanResult

type QuickScanResult struct {
	PipelineRunID string `json:"pipeline_run_id"`
	ScanID        string `json:"scan_id"`
	AssetGroupID  string `json:"asset_group_id"`
	Status        string `json:"status"`
	TargetCount   int    `json:"target_count"`
}

QuickScanResult represents the result of a quick scan.

type ScanConfigExport added in v0.1.2

type ScanConfigExport struct {
	// Metadata
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`

	// Targets
	AssetGroupIDs []string `json:"asset_group_ids,omitempty"`
	Targets       []string `json:"targets,omitempty"`

	// Scan Type
	ScanType      string         `json:"scan_type"`
	PipelineID    *string        `json:"pipeline_id,omitempty"`
	ScannerName   string         `json:"scanner_name,omitempty"`
	ScannerConfig map[string]any `json:"scanner_config,omitempty"`
	TargetsPerJob int            `json:"targets_per_job"`

	// Schedule
	ScheduleType     string  `json:"schedule_type"`
	ScheduleCron     string  `json:"schedule_cron,omitempty"`
	ScheduleDay      *int    `json:"schedule_day,omitempty"`
	ScheduleTime     *string `json:"schedule_time,omitempty"`
	ScheduleTimezone string  `json:"schedule_timezone"`

	// Routing
	Tags              []string `json:"tags,omitempty"`
	RunOnTenantRunner bool     `json:"run_on_tenant_runner"`
	AgentPreference   string   `json:"agent_preference,omitempty"`

	// Profile and timeout
	ProfileID      string `json:"profile_id,omitempty"`
	TimeoutSeconds int    `json:"timeout_seconds,omitempty"`

	// Retry config
	MaxRetries          int `json:"max_retries,omitempty"`
	RetryBackoffSeconds int `json:"retry_backoff_seconds,omitempty"`

	// Export metadata
	ExportedAt string `json:"exported_at"`
	Version    string `json:"version"`
}

ScanConfigExport represents the exportable configuration of a scan. It excludes runtime data like status, execution stats, and timestamps.

type SecurityValidator

type SecurityValidator interface {
	ValidateIdentifier(value string, maxLen int, fieldName string) *ValidationResult
	ValidateIdentifiers(values []string, maxLen int, fieldName string) *ValidationResult
	ValidateScannerConfig(ctx context.Context, tenantID shared.ID, config map[string]any) *ValidationResult
	ValidateCronExpression(cronExpr string) error
}

SecurityValidator interface for security validation.

type SelectAgentRequest

type SelectAgentRequest struct {
	TenantID     shared.ID
	Capabilities []string
	Tool         string
	Mode         SelectMode
	AllowQueue   bool
}

SelectAgentRequest represents a request to select an agent.

type SelectAgentResult

type SelectAgentResult struct {
	Agent      *agent.Agent
	IsPlatform bool
}

SelectAgentResult represents the result of agent selection.

type SelectMode

type SelectMode int

SelectMode represents the agent selection mode.

const (
	// SelectTenantFirst tries tenant agents first, then platform.
	SelectTenantFirst SelectMode = iota
)

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service handles scan business operations.

func NewService

func NewService(
	scanRepo scan.Repository,
	templateRepo pipeline.TemplateRepository,
	assetGroupRepo assetgroup.Repository,
	runRepo pipeline.RunRepository,
	stepRepo pipeline.StepRepository,
	stepRunRepo pipeline.StepRunRepository,
	commandRepo command.Repository,
	scannerTemplateRepo scannertemplate.Repository,
	templateSourceRepo templatesource.Repository,
	toolRepo tool.Repository,
	templateSyncer TemplateSyncer,
	agentSelector AgentSelector,
	securityValidator SecurityValidator,
	log *logger.Logger,
	opts ...ServiceOption,
) *Service

NewService creates a new Service.

func (*Service) ActivateScan

func (s *Service) ActivateScan(ctx context.Context, tenantID, scanID string) (*scan.Scan, error)

ActivateScan activates a scan.

func (*Service) BulkActivate

func (s *Service) BulkActivate(ctx context.Context, tenantID string, scanIDs []string) (*BulkActionResult, error)

BulkActivate activates multiple scans.

func (*Service) BulkDelete

func (s *Service) BulkDelete(ctx context.Context, tenantID string, scanIDs []string) (*BulkActionResult, error)

BulkDelete deletes multiple scans.

func (*Service) BulkDisable

func (s *Service) BulkDisable(ctx context.Context, tenantID string, scanIDs []string) (*BulkActionResult, error)

BulkDisable disables multiple scans.

func (*Service) BulkPause

func (s *Service) BulkPause(ctx context.Context, tenantID string, scanIDs []string) (*BulkActionResult, error)

BulkPause pauses multiple scans.

func (*Service) CloneScan

func (s *Service) CloneScan(ctx context.Context, tenantID, scanID, newName string) (*scan.Scan, error)

CloneScan clones a scan with a new name.

func (*Service) CreateScan

func (s *Service) CreateScan(ctx context.Context, input CreateScanInput) (*scan.Scan, error)

CreateScan creates a new scan.

func (*Service) DeactivateScansByPipeline

func (s *Service) DeactivateScansByPipeline(ctx context.Context, pipelineID shared.ID) (int, error)

DeactivateScansByPipeline pauses all active scans that use the specified pipeline. This implements the ScanDeactivator interface for cascade deactivation. Scans are paused (not disabled) so they can be easily resumed when the pipeline is reactivated. Returns the count of paused scans.

func (*Service) DeleteScan

func (s *Service) DeleteScan(ctx context.Context, tenantID, scanID string) error

DeleteScan deletes a scan.

func (*Service) DisableScan

func (s *Service) DisableScan(ctx context.Context, tenantID, scanID string) (*scan.Scan, error)

DisableScan disables a scan.

func (*Service) ExportConfig added in v0.1.2

func (s *Service) ExportConfig(ctx context.Context, tenantID, scanID shared.ID) ([]byte, error)

ExportConfig exports a scan configuration as JSON bytes. It strips runtime data (status, results, timestamps) and returns only the configuration fields needed to recreate the scan.

func (*Service) GetLatestScanRun

func (s *Service) GetLatestScanRun(ctx context.Context, tenantID, scanID string) (*pipeline.Run, error)

GetLatestScanRun gets the latest run for a specific scan.

func (*Service) GetOverviewStats

func (s *Service) GetOverviewStats(ctx context.Context, tenantID string) (*OverviewStats, error)

GetOverviewStats returns aggregated statistics for scan management. This includes pipeline runs, step runs (scans), and commands (jobs).

func (*Service) GetScan

func (s *Service) GetScan(ctx context.Context, tenantID, scanID string) (*scan.Scan, error)

GetScan retrieves a scan by ID.

func (*Service) GetScanRun

func (s *Service) GetScanRun(ctx context.Context, tenantID, scanID, runID string) (*pipeline.Run, error)

GetScanRun gets a specific run for a scan.

func (*Service) GetStats

func (s *Service) GetStats(ctx context.Context, tenantID string) (*scan.Stats, error)

GetStats returns aggregated statistics for scans.

func (*Service) ImportConfig added in v0.1.2

func (s *Service) ImportConfig(ctx context.Context, tenantID shared.ID, data []byte) (*scan.Scan, error)

ImportConfig creates a new scan from imported JSON configuration. The imported config is validated and a new scan entity is created.

func (*Service) ListScanRuns

func (s *Service) ListScanRuns(ctx context.Context, tenantID, scanID string, page, perPage int) (map[string]any, error)

ListScanRuns lists runs for a specific scan.

func (*Service) ListScans

func (s *Service) ListScans(ctx context.Context, input ListScansInput) (pagination.Result[*scan.Scan], error)

ListScans lists scans with filters.

func (*Service) PauseScan

func (s *Service) PauseScan(ctx context.Context, tenantID, scanID string) (*scan.Scan, error)

PauseScan pauses a scan.

func (*Service) PreviewScanCompatibility

func (s *Service) PreviewScanCompatibility(
	ctx context.Context,
	scannerName string,
	assetGroupIDs []shared.ID,
) (*AssetCompatibilityPreview, error)

PreviewScanCompatibility checks asset-scanner compatibility for a scan configuration. This is called before scan creation to show warnings about incompatible assets. Returns nil if no warning needed (100% compatible or no asset groups).

func (*Service) QuickScan

func (s *Service) QuickScan(ctx context.Context, input QuickScanInput) (*QuickScanResult, error)

QuickScan performs an immediate scan on provided targets. It creates an ephemeral asset group and scan, then triggers immediately.

func (*Service) RetryScanRun added in v0.1.5

func (s *Service) RetryScanRun(ctx context.Context, tenantID, scanID shared.ID, retryAttempt int) error

RetryScanRun creates a new pipeline run for a scan as part of automatic retry. Called by the ScanRetryController when a previous run failed and the scan has retry budget remaining.

The new run is tagged with retry_attempt = previous attempt + 1.

func (*Service) TriggerScan

func (s *Service) TriggerScan(ctx context.Context, input TriggerScanExecInput) (*pipeline.Run, error)

TriggerScan triggers a scan execution.

func (*Service) UpdateScan

func (s *Service) UpdateScan(ctx context.Context, input UpdateScanInput) (*scan.Scan, error)

UpdateScan updates a scan.

type ServiceOption

type ServiceOption func(*Service)

ServiceOption is a functional option for Service.

func WithAuditService

func WithAuditService(auditService AuditService) ServiceOption

WithAuditService sets the audit service for Service.

func WithProfileRepo added in v0.1.5

func WithProfileRepo(repo scanprofile.Repository) ServiceOption

WithProfileRepo sets the scan profile repository for ScanProfile linking and quality gates.

func WithTargetMappingRepo

func WithTargetMappingRepo(repo tool.TargetMappingRepository) ServiceOption

WithTargetMappingRepo sets the target mapping repository for asset-scanner compatibility.

type SkipReason

type SkipReason struct {
	AssetType string `json:"asset_type"`
	Count     int    `json:"count"`
	Reason    string `json:"reason"`
}

SkipReason explains why assets of a certain type were skipped.

type StatusCounts

type StatusCounts struct {
	Total     int64 `json:"total"`
	Running   int64 `json:"running"`
	Pending   int64 `json:"pending"`
	Completed int64 `json:"completed"`
	Failed    int64 `json:"failed"`
	Canceled  int64 `json:"canceled"`
}

StatusCounts represents counts grouped by status.

type TemplateSyncResult

type TemplateSyncResult struct {
	Success        bool
	TemplatesFound int
	TemplatesAdded int
}

TemplateSyncResult represents the result of syncing a template source.

type TemplateSyncer

type TemplateSyncer interface {
	SyncSource(ctx context.Context, source *templatesource.TemplateSource) (*TemplateSyncResult, error)
}

TemplateSyncer interface for template sync operations.

type TriggerScanExecInput

type TriggerScanExecInput struct {
	TenantID    string         `json:"tenant_id" validate:"required,uuid"`
	ScanID      string         `json:"scan_id" validate:"required,uuid"`
	TriggeredBy string         `json:"triggered_by" validate:"omitempty,uuid"`
	Context     map[string]any `json:"context"`
}

TriggerScanExecInput represents the input for triggering a scan execution.

type UpdateScanInput

type UpdateScanInput struct {
	TenantID        string         `json:"tenant_id" validate:"required,uuid"`
	ScanID          string         `json:"scan_id" validate:"required,uuid"`
	Name            string         `json:"name" validate:"omitempty,min=1,max=200"`
	Description     string         `json:"description" validate:"max=1000"`
	PipelineID      string         `json:"pipeline_id" validate:"omitempty,uuid"`
	ScannerName     string         `json:"scanner_name" validate:"max=100"`
	ScannerConfig   map[string]any `json:"scanner_config"`
	TargetsPerJob   *int           `json:"targets_per_job"`
	ScheduleType    string         `json:"schedule_type" validate:"omitempty,oneof=manual daily weekly monthly crontab"`
	ScheduleCron    string         `json:"schedule_cron" validate:"max=100"`
	ScheduleDay     *int           `json:"schedule_day"`
	ScheduleTime    *time.Time     `json:"schedule_time"`
	Timezone        string         `json:"timezone" validate:"max=50"`
	Tags            []string       `json:"tags" validate:"max=20,dive,max=50"`
	TenantRunner    *bool          `json:"run_on_tenant_runner"`
	AgentPreference string         `json:"agent_preference" validate:"omitempty,oneof=auto tenant platform"`
	// ProfileID: pointer with sentinel:
	//   nil           = leave unchanged
	//   pointer to "" = unlink profile
	//   pointer to id = link to profile
	ProfileID *string `json:"profile_id" validate:"omitempty"`
	// TimeoutSeconds: nil = leave unchanged, otherwise min=30 max=86400
	TimeoutSeconds *int `json:"timeout_seconds" validate:"omitempty,min=30,max=86400"`
	// Retry config: nil = leave unchanged
	MaxRetries          *int `json:"max_retries" validate:"omitempty,min=0,max=10"`
	RetryBackoffSeconds *int `json:"retry_backoff_seconds" validate:"omitempty,min=10,max=86400"`
}

UpdateScanInput represents the input for updating a scan.

type ValidationError

type ValidationError struct {
	Field   string
	Message string
	Code    string
}

ValidationError represents a validation error.

type ValidationResult

type ValidationResult struct {
	Valid  bool
	Errors []ValidationError
}

ValidationResult represents the result of a validation.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL