- Implement cloud provider infrastructure (DigitalOcean, AWS, GCP, Linode, Azure) with Pulumi integration for distributed scanning - Add nmap and tmux utility functions for port scanning results processing and long-running background session management - Introduce webhook-triggered run execution with unique UUID and authentication key support for external integrations
Cloud Infrastructure Feature - Implementation Summary
Overview
This implementation provides the foundation for automated cloud infrastructure provisioning using Pulumi's Go SDK, enabling users to spin up ephemeral worker nodes across multiple cloud providers for distributed scanning.
What Was Implemented
✅ Phase 1: Foundation (COMPLETED)
1. Package Structure
Created /internal/cloud/ with the following files:
config.go- Cloud config loading, validation, and environment variable resolutionprovider.go- Provider interface and type definitionspulumi.go- Pulumi Automation API wrapperlifecycle.go- Orchestration logic (create → run → collect → destroy)cost.go- Cost tracking and limit enforcementstate.go- Infrastructure state persistence (JSON format)worker.go- Worker registration waiting and filteringregistry.go- Provider factory and registrationdigitalocean.go- DigitalOcean provider implementation (foundation)
2. Configuration System
-
Extended
/internal/config/config.go:- Added
CloudConfigstruct to mainConfig - Added cloud section to embedded YAML template
- Added
-
Created
/internal/config/cloud_config.go:CloudConfigsstruct matching YAML schema- Provider configs (AWS, GCP, DigitalOcean, Linode, Azure)
- Defaults, Limits, State, SSH, Setup sections
DefaultCloudConfigs()factory function
-
Environment Variable Resolution:
- Supports
${VAR_NAME}syntax in config values - Automatically expands on load
- Supports
3. CLI Commands
Created /pkg/cli/cloud.go with full command tree:
osmedeus cloud
├── config
│ ├── set <key> <value> # Update cloud-settings.yaml
│ └── show # Display current config
├── create # Provision infrastructure
├── list # List active resources
├── destroy [id] # Teardown infrastructure
└── run # Create + run workflow + destroy
Flags:
--provider- Override default provider--mode- vm or serverless--instances- Number of instances--force- Force rebuild
Registered in /pkg/cli/root.go (line 309)
4. Dependencies
Added to go.mod:
github.com/pulumi/pulumi/sdk/v3(v3.220.0)github.com/pulumi/pulumi-digitalocean/sdk/v4(v4.57.0)github.com/digitalocean/godo(v1.175.0)
5. Core Abstractions
Provider Interface:
type Provider interface {
Validate(ctx) error
EstimateCost(mode, count) (*CostEstimate, error)
CreateInfrastructure(ctx, opts) (*Infrastructure, error)
DestroyInfrastructure(ctx, infra) error
GetStatus(ctx, infra) (*InfraStatus, error)
Type() ProviderType
}
Key Types:
ProviderType: aws, gcp, digitalocean, linode, azureExecutionMode: vm (Phase 1), serverless (Phase 2)Infrastructure: Resources, Pulumi stack ID, metadataResource: VM/function details, IPs, worker ID, statusCostEstimate: Hourly/daily rates, breakdown, notes
LifecycleManager:
- Cost validation before provisioning
- Worker registration waiting (polls every 5s)
- Graceful shutdown on SIGINT/SIGTERM
- Cleanup on failure (configurable)
CostTracker:
- Real-time cost calculation based on elapsed time
- Limit enforcement (max_hourly_spend, max_total_spend)
- Summary formatting for display
State Management:
- JSON persistence in
{{base_folder}}/cloud-state/infrastructure/ SaveInfrastructureState()/LoadInfrastructureState()ListInfrastructures()forcloud listcommand- Recovery from interruptions
Worker Integration:
WaitForWorkers()pollsdistributed.Client.GetAllWorkers()- Filters by
wosm-orcloud-prefix - Timeout handling (default 5min)
- Status callback support
6. DigitalOcean Provider (Foundation)
- Provider struct: Token, region, size, snapshot, SSH keys, godo client
- Validation: Tests API access via account info
- Cost estimation: Pricing map for common droplet sizes
- Cloud-init script: Installs osmedeus, sets up SSH, joins as worker
- Pulumi integration: Placeholder for
digitalocean.Dropletresources
What's NOT Yet Implemented
⏳ Phase 2: Completion Tasks
-
DigitalOcean Droplet Creation
- Complete
createDropletProgram()with actual Pulumi resources - SSH key creation/upload
- Firewall rules
- Output extraction (IPs, droplet IDs)
- Status monitoring
- Complete
-
Result Collection
- SSH rsync integration from
internal/runner - Workspace aggregation on master
- Optional database import via
db_import_*functions
- SSH rsync integration from
-
Cloud Run Workflow
- Full lifecycle: create → wait → submit tasks → monitor → collect → destroy
- Distributed task submission via
distributed.Master - Progress UI via
terminal.Printer - Cost monitoring ticker
-
Error Handling
- Robust retry logic
- Partial failure handling
- Resource leak prevention
- Better error messages
-
Additional Providers
- AWS EC2 implementation
- GCP Compute Engine implementation
- Linode implementation
- Azure implementation
-
Image Building
cloud buildcommand to create provider images/snapshots- Packer integration or provider-native tools
- Pre-baked osmedeus images for faster boot
-
Testing
- Unit tests for config, cost, state
- Integration tests (requires cloud credentials)
- End-to-end test script
- Cost limit validation tests
-
Documentation
- Usage examples in CLAUDE.md
- API documentation
- Troubleshooting guide
Testing the Current Implementation
Build Test
make fmt && make build
# ✅ Compiles successfully (152MB binary)
CLI Test
./bin/osmedeus cloud --help
# ✅ Shows cloud command help
./bin/osmedeus cloud config --help
# ✅ Shows config subcommands
./bin/osmedeus cloud create --help
# ✅ Shows create flags
Config Test
# Set a config value
osmedeus cloud config set defaults.provider digitalocean
osmedeus cloud config set providers.digitalocean.token ${DIGITALOCEAN_TOKEN}
# Show current config
osmedeus cloud config show
Architecture Decisions
- Local Pulumi State: No Pulumi Cloud account required, state stored in
{{base_folder}}/cloud-state/ - Provider in Same Package: Moved from
cloud/providers/tocloud/to avoid import cycles - Worker Auto-Registration: Leverages existing
distributed.Workersystem, no custom registration needed - State Persistence: JSON format for easy inspection and debugging
- Cost Tracking: Proactive limits prevent accidental overspending
- Graceful Shutdown: Signal handlers ensure cleanup even on interruption
Next Steps for Full Implementation
Priority 1: Complete DigitalOcean Provider
- Implement full Pulumi program in
createDropletProgram() - Add SSH key management
- Extract outputs (IPs, IDs) from Pulumi stack
- Test single-instance creation end-to-end
Priority 2: Implement Cloud Run Workflow
- Add distributed task submission logic
- Integrate cost monitoring ticker
- Add confirmation prompts
- Test full lifecycle with simple workflow
Priority 3: Result Collection
- Integrate SSH runner's
CopyFromRemote() - Aggregate results to master workspace
- Optional: Auto-import to master database
Priority 4: Error Handling & Polish
- Add retry logic for API failures
- Better error messages
- Progress indicators
- Confirmation prompts
Files Modified
Created
/internal/cloud/*.go(9 files)/internal/config/cloud_config.go/pkg/cli/cloud.go/internal/cloud/README.md(this file)
Modified
/internal/config/config.go(added CloudConfig struct + YAML template)/pkg/cli/root.go(registered cloudCmd)go.mod(added Pulumi + DigitalOcean dependencies)
Summary
The cloud infrastructure feature foundation is complete and compiles successfully. The architecture is sound, the CLI is functional, and the abstractions are clean. The remaining work is primarily:
- Completing the DigitalOcean Pulumi program
- Implementing the cloud run workflow orchestration
- Adding result collection via SSH
- Testing end-to-end with real cloud resources
The implementation follows Osmedeus patterns (Cobra CLI, YAML config, terminal printer) and integrates seamlessly with the existing distributed system.