Skip to content

Commit

Permalink
refactor: provider configuration (#388)
Browse files Browse the repository at this point in the history
* refactor: provider config

* fix: using provider enum

* refactor: use struct tags for unmarshaling

* fix: wording for config validation errors
  • Loading branch information
chrisgacsal committed Jun 14, 2023
1 parent d594f99 commit fbd40fd
Show file tree
Hide file tree
Showing 11 changed files with 308 additions and 96 deletions.
9 changes: 4 additions & 5 deletions backend/pkg/backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import (
databaseTypes "github.com/openclarity/vmclarity/backend/pkg/database/types"
"github.com/openclarity/vmclarity/backend/pkg/rest"
"github.com/openclarity/vmclarity/runtime_scan/pkg/orchestrator"
"github.com/openclarity/vmclarity/runtime_scan/pkg/provider/aws"
"github.com/openclarity/vmclarity/shared/pkg/backendclient"
"github.com/openclarity/vmclarity/shared/pkg/log"
uibackend "github.com/openclarity/vmclarity/ui_backend/pkg/rest"
Expand Down Expand Up @@ -129,15 +128,15 @@ func Run(ctx context.Context) {
func startOrchestrator(ctx context.Context, config *_config.Config, client *backendclient.BackendClient) error {
orchestratorConfig, err := orchestrator.LoadConfig(config.BackendRestHost, config.BackendRestPort, rest.BaseURL)
if err != nil {
return fmt.Errorf("failed to load runtime scan orchestrator config: %w", err)
return fmt.Errorf("failed to load Orchestrator config: %w", err)
}

p, err := aws.New(ctx, orchestratorConfig.AWSConfig)
o, err := orchestrator.New(ctx, orchestratorConfig, client)
if err != nil {
return fmt.Errorf("failed to create provider client: %w", err)
return fmt.Errorf("failed to initialize Orchestrator: %w", err)
}

orchestrator.New(orchestratorConfig, p, client).Start(ctx)
o.Start(ctx)

return nil
}
46 changes: 46 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Configuration

## Orchestrator

| Environment Variable | Required | Default | Description |
|-------------------------------------------|-----------|---------|----------------------------------------------|
| `DELETE_JOB_POLICY` | | | |
| `SCANNER_CONTAINER_IMAGE` | | | |
| `GITLEAKS_BINARY_PATH` | | | |
| `CLAM_BINARY_PATHCLAM_BINARY_PATH` | | | |
| `FRESHCLAM_BINARY_PATH` | | | |
| `ALTERNATIVE_FRESHCLAM_MIRROR_URL` | | | |
| `LYNIS_INSTALL_PATH` | | | |
| `SCANNER_VMCLARITY_BACKEND_ADDRESS` | | | |
| `EXPLOIT_DB_ADDRESS` | | | |
| `TRIVY_SERVER_ADDRESS` | | | |
| `TRIVY_SERVER_TIMEOUT` | | | |
| `GRYPE_SERVER_ADDRESS` | | | |
| `GRYPE_SERVER_TIMEOUT` | | | |
| `CHKROOTKIT_BINARY_PATH` | | | |
| `SCAN_CONFIG_POLLING_INTERVAL` | | | |
| `SCAN_CONFIG_RECONCILE_TIMEOUT` | | | |
| `SCAN_POLLING_INTERVAL` | | | |
| `SCAN_RECONCILE_TIMEOUT` | | | |
| `SCAN_TIMEOUT` | | | |
| `SCAN_RESULT_POLLING_INTERVAL` | | | |
| `SCAN_RESULT_RECONCILE_TIMEOUT` | | | |
| `SCAN_RESULT_PROCESSOR_POLLING_INTERVAL` | | | |
| `SCAN_RESULT_PROCESSOR_RECONCILE_TIMEOUT` | | | |
| `DISCOVERY_INTERVAL` | | | |
| `CONTROLLER_STARTUP_DELAY` | | | |
| `PROVIDER` | **yes** | `aws` | Provider used for Target discovery and scans |

## Provider

### AWS

| Environment Variable | Required | Default | Description |
|----------------------------------------|----------|--------------|-------------------------------------------------------------------------------|
| `VMCLARITY_AWS_REGION` | **yes** | | Region where the Scanner instance needs to be created |
| `VMCLARITY_AWS_SUBNET_ID` | **yes** | | SubnetID where the Scanner instance needs to be created |
| `VMCLARITY_AWS_SECURITY_GROUP_ID` | **yes** | | SecurityGroupId which needs to be attached to the Scanner instance |
| `VMCLARITY_AWS_KEYPAIR_NAME` | | | Name of the SSH KeyPair to use for Scanner instance launch |
| `VMCLARITY_AWS_SCANNER_AMI_ID` | **yes** | | The AMI image used for creating Scanner instance |
| `VMCLARITY_AWS_SCANNER_INSTANCE_TYPE` | | `t2.large` | The instance type used for Scanner instance |
| `VMCLARITY_AWS_BLOCK_DEVICE_NAME` | | `xvdh` | Block device name used for attaching Scanner volume to the Scanner instance |
43 changes: 34 additions & 9 deletions installation/aws/VmClarity.cfn
Original file line number Diff line number Diff line change
Expand Up @@ -229,21 +229,46 @@ Resources:
content:
Fn::Sub:
- |
AWS_REGION=${AWS::Region}
SCANNER_AWS_REGION=${AWS::Region}
AWS_SUBNET_ID=${VmClarityScannerSubnet}
AWS_SECURITY_GROUP_ID=${VmClarityScannerSecurityGroup}
AWS_INSTANCE_TYPE=${ScannerInstanceType}
SCANNER_KEY_PAIR_NAME=${KeyName}
AWS_JOB_IMAGE_ID=${JobImageID}
##
## Orchestrator configuration
##
# Host for the VMClarity backend server
BACKEND_REST_HOST=__BACKEND_REST_HOST__
# Port number for the VMClarity backend server
BACKEND_REST_PORT=8888
# Container image for Scanner instance
SCANNER_CONTAINER_IMAGE=${ScannerContainerImage}
# Trivy server address
TRIVY_SERVER_ADDRESS=http://__BACKEND_REST_HOST__:9992
# Grype server address
GRYPE_SERVER_ADDRESS=__BACKEND_REST_HOST__:9991
DELETE_JOB_POLICY=${AssetScanDeletePolicy}
# FreshClam mirror URL
ALTERNATIVE_FRESHCLAM_MIRROR_URL=http://__BACKEND_REST_HOST__:1000/clamav
- JobImageID: !FindInMap
# Resource cleanup policy
DELETE_JOB_POLICY=${AssetScanDeletePolicy}
# Provider to use
PROVIDER=aws

##
## Provider configuration
##
# The AWS region where the provider is deployed
AWS_REGION=${AWS::Region}
# Region where the Scanner instance needs to be created
VMCLARITY_AWS_SCANNER_REGION=${AWS::Region}
# SubnetID where the Scanner instance needs to be created
VMCLARITY_AWS_SUBNET_ID=${VmClarityScannerSubnet}
# SecurityGroupId which needs to be attached to the Scanner instance
VMCLARITY_AWS_SECURITY_GROUP_ID=${VmClarityScannerSecurityGroup}
# Name of the SSH KeyPair to use for Scanner instance launch
VMCLARITY_AWS_KEYPAIR_NAME=${KeyName}
# The AMI image used for creating Scanner instance
VMCLARITY_AWS_SCANNER_AMI_ID=${ScannerImageID}
# The instance type used for Scanner instance
VMCLARITY_AWS_SCANNER_INSTANCE_TYPE=${ScannerInstanceType}
# Block device name used for attaching Scanner volume to the Scanner instance
#VMCLARITY_AWS_BLOCK_DEVICE_NAME=xvhd
- ScannerImageID: !FindInMap
- AWSRegionArch2AMI
- !Ref "AWS::Region"
- !FindInMap
Expand Down
35 changes: 17 additions & 18 deletions runtime_scan/pkg/orchestrator/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,31 +19,28 @@ import (
"fmt"
"net"
"strconv"
"strings"
"time"

"github.com/spf13/viper"

"github.com/openclarity/vmclarity/api/models"
"github.com/openclarity/vmclarity/runtime_scan/pkg/orchestrator/discovery"
"github.com/openclarity/vmclarity/runtime_scan/pkg/orchestrator/scanconfigwatcher"
"github.com/openclarity/vmclarity/runtime_scan/pkg/orchestrator/scanresultprocessor"
"github.com/openclarity/vmclarity/runtime_scan/pkg/orchestrator/scanresultwatcher"
"github.com/openclarity/vmclarity/runtime_scan/pkg/orchestrator/scanwatcher"
"github.com/openclarity/vmclarity/runtime_scan/pkg/provider/aws"
)

const (
ScannerAWSRegion = "SCANNER_AWS_REGION"
DeleteJobPolicy = "DELETE_JOB_POLICY"
ScannerContainerImage = "SCANNER_CONTAINER_IMAGE"
ScannerKeyPairName = "SCANNER_KEY_PAIR_NAME"
GitleaksBinaryPath = "GITLEAKS_BINARY_PATH"
ClamBinaryPath = "CLAM_BINARY_PATH"
FreshclamBinaryPath = "FRESHCLAM_BINARY_PATH"
AlternativeFreshclamMirrorURL = "ALTERNATIVE_FRESHCLAM_MIRROR_URL"
LynisInstallPath = "LYNIS_INSTALL_PATH"
AttachedVolumeDeviceName = "ATTACHED_VOLUME_DEVICE_NAME"
ScannerBackendAddress = "SCANNER_VMCLARITY_BACKEND_ADDRESS"
ScanConfigWatchInterval = "SCAN_CONFIG_WATCH_INTERVAL"
ExploitDBAddress = "EXPLOIT_DB_ADDRESS"
TrivyServerAddress = "TRIVY_SERVER_ADDRESS"
TrivyServerTimeout = "TRIVY_SERVER_TIMEOUT"
Expand All @@ -67,20 +64,21 @@ const (
DiscoveryInterval = "DISCOVERY_INTERVAL"

ControllerStartupDelay = "CONTROLLER_STARTUP_DELAY"

ProviderKind = "PROVIDER"
)

const (
DefaultScannerAWSRegion = "us-east-1"
DefaultAttachedVolumeDeviceName = "xvdh"

DefaultTrivyServerTimeout = 5 * time.Minute
DefaultGrypeServerTimeout = 2 * time.Minute

DefaultControllerStartupDelay = 15 * time.Second
DefaultProviderKind = models.AWS
)

type Config struct {
AWSConfig *aws.Config
ProviderKind models.CloudProvider

ScannerBackendAddress string

// The Orchestrator starts the Controller(s) in a sequence and the ControllerStartupDelay is used for waiting
Expand All @@ -96,8 +94,6 @@ type Config struct {
}

func setConfigDefaults(backendHost string, backendPort int, backendBaseURL string) {
viper.SetDefault(ScannerAWSRegion, DefaultScannerAWSRegion)
viper.SetDefault(ScanConfigWatchInterval, "30s")
viper.SetDefault(DeleteJobPolicy, string(scanresultwatcher.DeleteJobPolicyAlways))
viper.SetDefault(ScannerBackendAddress, fmt.Sprintf("http://%s%s", net.JoinHostPort(backendHost, strconv.Itoa(backendPort)), backendBaseURL))
// https://github.com/openclarity/vmclarity-tools-base/blob/main/Dockerfile#L33
Expand All @@ -107,7 +103,6 @@ func setConfigDefaults(backendHost string, backendPort int, backendBaseURL strin
// https://github.com/openclarity/vmclarity-tools-base/blob/main/Dockerfile
viper.SetDefault(ChkrootkitBinaryPath, "/artifacts/chkrootkit")
viper.SetDefault(ExploitDBAddress, fmt.Sprintf("http://%s", net.JoinHostPort(backendHost, "1326")))
viper.SetDefault(AttachedVolumeDeviceName, DefaultAttachedVolumeDeviceName)
viper.SetDefault(ClamBinaryPath, "clamscan")
viper.SetDefault(FreshclamBinaryPath, "freshclam")
viper.SetDefault(TrivyServerTimeout, DefaultTrivyServerTimeout)
Expand All @@ -123,18 +118,25 @@ func setConfigDefaults(backendHost string, backendPort int, backendBaseURL strin
viper.SetDefault(ScanResultProcessorReconcileTimeout, scanresultprocessor.DefaultReconcileTimeout.String())
viper.SetDefault(DiscoveryInterval, discovery.DefaultInterval.String())
viper.SetDefault(ControllerStartupDelay, DefaultControllerStartupDelay.String())
viper.SetDefault(ProviderKind, DefaultProviderKind)

viper.AutomaticEnv()
}

func LoadConfig(backendHost string, backendPort int, baseURL string) (*Config, error) {
setConfigDefaults(backendHost, backendPort, baseURL)

c := &Config{
AWSConfig: aws.LoadConfig(),
var providerKind models.CloudProvider
switch strings.ToLower(viper.GetString(ProviderKind)) {
case strings.ToLower(string(models.AWS)):
fallthrough
default:
providerKind = models.AWS
}

c := &Config{
ProviderKind: providerKind,
ControllerStartupDelay: viper.GetDuration(ControllerStartupDelay),

DiscoveryConfig: discovery.Config{
DiscoveryInterval: viper.GetDuration(DiscoveryInterval),
},
Expand All @@ -152,14 +154,11 @@ func LoadConfig(backendHost string, backendPort int, baseURL string) (*Config, e
PollPeriod: viper.GetDuration(ScanResultPollingInterval),
ReconcileTimeout: viper.GetDuration(ScanResultReconcileTimeout),
ScannerConfig: scanresultwatcher.ScannerConfig{
Region: viper.GetString(ScannerAWSRegion),
DeleteJobPolicy: scanresultwatcher.GetDeleteJobPolicyType(viper.GetString(DeleteJobPolicy)),
ScannerImage: viper.GetString(ScannerContainerImage),
ScannerBackendAddress: viper.GetString(ScannerBackendAddress),
ScannerKeyPairName: viper.GetString(ScannerKeyPairName),
GitleaksBinaryPath: viper.GetString(GitleaksBinaryPath),
LynisInstallPath: viper.GetString(LynisInstallPath),
DeviceName: viper.GetString(AttachedVolumeDeviceName),
ExploitsDBAddress: viper.GetString(ExploitDBAddress),
ClamBinaryPath: viper.GetString(ClamBinaryPath),
FreshclamBinaryPath: viper.GetString(FreshclamBinaryPath),
Expand Down
35 changes: 32 additions & 3 deletions runtime_scan/pkg/orchestrator/orchestrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,17 @@ package orchestrator

import (
"context"
"fmt"
"time"

"github.com/openclarity/vmclarity/api/models"
"github.com/openclarity/vmclarity/runtime_scan/pkg/orchestrator/discovery"
"github.com/openclarity/vmclarity/runtime_scan/pkg/orchestrator/scanconfigwatcher"
"github.com/openclarity/vmclarity/runtime_scan/pkg/orchestrator/scanresultprocessor"
"github.com/openclarity/vmclarity/runtime_scan/pkg/orchestrator/scanresultwatcher"
"github.com/openclarity/vmclarity/runtime_scan/pkg/orchestrator/scanwatcher"
"github.com/openclarity/vmclarity/runtime_scan/pkg/provider"
"github.com/openclarity/vmclarity/runtime_scan/pkg/provider/aws"
"github.com/openclarity/vmclarity/shared/pkg/backendclient"
"github.com/openclarity/vmclarity/shared/pkg/log"
)
Expand All @@ -36,7 +39,10 @@ type Orchestrator struct {
controllerStartupDelay time.Duration
}

func New(config *Config, p provider.Provider, b *backendclient.BackendClient) *Orchestrator {
// NewWithProvider returns an Orchestrator initialized using the p provider.Provider.
// Use this method when Orchestrator needs to rely on custom provider.Provider implementation.
// E.g. End-to-End testing.
func NewWithProvider(config *Config, p provider.Provider, b *backendclient.BackendClient) (*Orchestrator, error) {
scanConfigWatcherConfig := config.ScanConfigWatcherConfig.WithBackendClient(b)
discoveryConfig := config.DiscoveryConfig.WithBackendClient(b).WithProviderClient(p)
scanWatcherConfig := config.ScanWatcherConfig.WithBackendClient(b).WithProviderClient(p)
Expand All @@ -52,11 +58,22 @@ func New(config *Config, p provider.Provider, b *backendclient.BackendClient) *O
scanresultwatcher.New(scanResultWatcherConfig),
},
controllerStartupDelay: config.ControllerStartupDelay,
}, nil
}

// New returns a new Orchestrator initialized using the provided configuration.
func New(ctx context.Context, config *Config, b *backendclient.BackendClient) (*Orchestrator, error) {
p, err := NewProvider(ctx, config.ProviderKind)
if err != nil {
return nil, fmt.Errorf("failed to initialize provider. Provider=%s: %w", config.ProviderKind, err)
}

return NewWithProvider(config, p, b)
}

// Start makes the Orchestrator to start all Controller(s).
func (o *Orchestrator) Start(ctx context.Context) {
log.GetLoggerFromContextOrDiscard(ctx).Infof("Starting Orchestrator server")
log.GetLoggerFromContextOrDiscard(ctx).Info("Starting Orchestrator server")

ctx, cancel := context.WithCancel(ctx)
o.cancelFunc = cancel
Expand All @@ -67,10 +84,22 @@ func (o *Orchestrator) Start(ctx context.Context) {
}
}

// Start makes the Orchestrator to stop all Controller(s).
func (o *Orchestrator) Stop(ctx context.Context) {
log.GetLoggerFromContextOrDiscard(ctx).Infof("Stopping Orchestrator server")
log.GetLoggerFromContextOrDiscard(ctx).Info("Stopping Orchestrator server")

if o.cancelFunc != nil {
o.cancelFunc()
}
}

// nolint:wrapcheck
// NewProvider returns an initialized provider.Provider based on the kind models.CloudProvider.
func NewProvider(ctx context.Context, kind models.CloudProvider) (provider.Provider, error) {
switch kind {
case models.AWS:
return aws.New(ctx)
default:
return nil, fmt.Errorf("unsupported provider: %s", kind)
}
}
13 changes: 0 additions & 13 deletions runtime_scan/pkg/orchestrator/scanresultwatcher/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,6 @@ func (c Config) WithScannerConfig(s ScannerConfig) Config {
}

type ScannerConfig struct {
// We need to know where the VMClarity scanner is running so that we
// can boot the scanner jobs in the same region, there isn't a
// mechanism to discover this right now so its passed in as a config
// value.
Region string

// Address that the Scanner should use to talk to the VMClarity backend
// We use a configuration variable for this instead of discovering it
// automatically in case VMClarity backend has multiple IPs (internal
Expand All @@ -89,10 +83,6 @@ type ScannerConfig struct {
// tools.
ScannerImage string

// The key pair name that should be attached to the scanner VM instance.
// Mainly used for debugging.
ScannerKeyPairName string

// The gitleaks binary path in the scanner image container.
GitleaksBinaryPath string

Expand All @@ -110,7 +100,4 @@ type ScannerConfig struct {

// The chkrootkit binary path in the scanner image container.
ChkrootkitBinaryPath string

// the name of the block device to attach to the scanner job
DeviceName string
}
3 changes: 0 additions & 3 deletions runtime_scan/pkg/orchestrator/scanresultwatcher/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,6 @@ func newJobConfig(i *jobConfigInput) (*provider.ScanJobConfig, error) {
ScannerImage: i.config.ScannerImage,
ScannerCLIConfig: string(scannerConfigYAML),
VMClarityAddress: i.config.ScannerBackendAddress,
KeyPairName: i.config.ScannerKeyPairName,
ScannerRegion: i.config.Region,
BlockDeviceName: i.config.DeviceName,
ScanMetadata: provider.ScanMetadata{
ScanID: i.scanResult.Scan.Id,
ScanResultID: *i.scanResult.Id,
Expand Down
Loading

0 comments on commit fbd40fd

Please sign in to comment.