-
Notifications
You must be signed in to change notification settings - Fork 22
Conversation
Signed-off-by: Peter Balogh <[email protected]>
Signed-off-by: Peter Balogh <[email protected]>
Signed-off-by: Peter Balogh <[email protected]>
Signed-off-by: Peter Balogh <[email protected]>
Signed-off-by: Peter Balogh <[email protected]>
Signed-off-by: Peter Balogh <[email protected]>
Signed-off-by: Peter Balogh <[email protected]>
cli/cmd/root.go
Outdated
rootCmd.PersistentFlags().StringVar(&scanResultID, "scan-result-id", "", "the ScanResult ID to export the scan results to") | ||
rootCmd.PersistentFlags().BoolVar(&mountVolume, "mount-attached-volume", false, "discover for an attached volume and mount it before the scan") | ||
rootCmd.PersistentFlags().BoolVar(&waitForServerAttached, "wait-for-server-attached", false, "wait for the VMClarity server to attach the volume") | ||
rootCmd.PersistentFlags().StringVar(&input, "input", "", "input for families") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what do you mean by input (and input type) for families? it will replace the input from config? is that only for the cicd mode?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The input can be a different type in the case of CICD mode. For example, it can be a directory and in the future we have to support container image, container info, and vm image input type. It makes sense only CICD mode because in orchestrated mode we are scanning VMs at the moment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO the input for all this should be the VMClarity CLI input yaml, ideally the CLI should have little to no command line arguments so that backwards compatibility is easier to maintain. For example the yaml could look something like:
asset:
type: VM
...
loadFamilySettingsFromScanConfig: <ID or Name>
sbom:
inputs:
- type: ROOTFS
path: /
If we want to provide the option to run VMClarity CLI without a yaml input, then IMO CLI flags we provide should be direct overrides of the options in the yaml "helm style" e.g. --set asset.type=VM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agree, not sure why we need different cli flags for that mode
Signed-off-by: Peter Balogh <[email protected]>
api/openapi.yaml
Outdated
@@ -1442,12 +1442,18 @@ components: | |||
- $ref: '#/components/schemas/VMInfo' | |||
- $ref: '#/components/schemas/PodInfo' | |||
- $ref: '#/components/schemas/DirInfo' | |||
- $ref: '#/components/schemas/VMImage' | |||
- $ref: '#/components/schemas/ContainerInfo' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure why this is "ContainerInfo" and not just container... I think the same for the existing types too... why is it "VMInfo" and not just TargetType: "VM"... :/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new target types were removed now.
api/openapi.yaml
Outdated
objectType: | ||
type: string | ||
containerName: | ||
type: string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need some info about where the container is running and the image that its based on etc right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
new targets were removed
Reason: fmt.Sprintf("Target directory exists with same name=%q and location=%q", *info.DirName, *info.Location), | ||
} | ||
} | ||
return nil, nil // nolint:nilnil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we're adding the other types in the API should make sure they are all covered here otherwise we won't be able to use them
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
new targets were removed
cli/cmd/root.go
Outdated
rootCmd.PersistentFlags().StringVar(&scanResultID, "scan-result-id", "", "the ScanResult ID to export the scan results to") | ||
rootCmd.PersistentFlags().BoolVar(&mountVolume, "mount-attached-volume", false, "discover for an attached volume and mount it before the scan") | ||
rootCmd.PersistentFlags().BoolVar(&waitForServerAttached, "wait-for-server-attached", false, "wait for the VMClarity server to attach the volume") | ||
rootCmd.PersistentFlags().StringVar(&input, "input", "", "input for families") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO the input for all this should be the VMClarity CLI input yaml, ideally the CLI should have little to no command line arguments so that backwards compatibility is easier to maintain. For example the yaml could look something like:
asset:
type: VM
...
loadFamilySettingsFromScanConfig: <ID or Name>
sbom:
inputs:
- type: ROOTFS
path: /
If we want to provide the option to run VMClarity CLI without a yaml input, then IMO CLI flags we provide should be direct overrides of the options in the yaml "helm style" e.g. --set asset.type=VM
cli/pkg/cicd/vminfoprovider/aws.go
Outdated
if err != nil { | ||
return "", "", fmt.Errorf("failed to read availability-zone response body: %v", err) | ||
} | ||
az := string(availabilityZone) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can just query http://169.254.169.254/latest/meta-data/placement/region
for the region, then there is no need to post-process it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thx, I missed it somehow.
cli/pkg/cli/cli.go
Outdated
@@ -39,6 +40,7 @@ const ( | |||
type CLI struct { | |||
state.Manager | |||
presenter.Presenter | |||
updater.Updater |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think there is a need for a new concept here, I think almost everything can be hidden inside the existing state.Manager and presenter.Presenter concepts, if we create a new "CICDStateManagerPresenter" which wraps the VMClarity state manager and presenter, the "WaitForVolumeAttachment" and "IsAborted" functions can be empty.
"MarkInProgress" can:
- Create the Asset as Defined by the user
- Create a Scan with just that Asset defined as the scanned asset
- Create a ScanResult with that Scan ID
- Call the VMClarity state manager MarkInProgress with the ScanResult ID
then "MarkDone" can:
- Call the normal VMClarity state manager MarkDone
- Update the Scan with the summary from the ScanResult and mark it as completed.
All the presenter functions will be passed straight through except the ScanResult ID from MarkInProgress will be injected. This way the work that Erez is doing to allow for incremental status updates etc will still work even in the CI/CD flow.
If we don't need the incremental updates stuff and we don't want a Scan in the system until we've succeeded, we can leave MarkInProgress empty, and then cache all the results as they arrive through our presenter interface, and then do everything we need to do in the "MarkDone".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The update was removed from the cli
runtime_scan/pkg/config/config.go
Outdated
|
||
GrypeServerAddress string | ||
// Scanner server and exploit DB addresses for families | ||
FamiliesAddresses families.Addresses |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we changing this in this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed back
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure this belongs in shared, this requires families logic to know about the VMClarity API concepts. If we want to put it anywhere "common" it should be in the VMClarity CLI package, and then the runtime_scan can import it from there.
shared/pkg/families/config.go
Outdated
ChkrootkitBinaryPath = "CHKROOTKIT_BINARY_PATH" | ||
ExploitDBAddress = "EXPLOIT_DB_ADDRESS" | ||
TrivyServerAddress = "TRIVY_SERVER_ADDRESS" | ||
GrypeServerAddress = "GRYPE_SERVER_ADDRESS" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
families logic should only receive a configuration struct from the outside, it should not be doing any loading of configurations itself, that is the responsibility of the CLI.
The CLI code uses viper + yaml, we should not be using environment variables like this anywhere in this flow, and if we want defaults then we should be handling it as part of loading that configuration. E.g. setting a default for rootkits.scannerconfig.chkrootkit.binarypath.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed from families
Signed-off-by: Peter Balogh <[email protected]>
Signed-off-by: Peter Balogh <[email protected]>
Signed-off-by: Peter Balogh <[email protected]>
Signed-off-by: Peter Balogh <[email protected]>
Signed-off-by: Peter Balogh <[email protected]>
Signed-off-by: Peter Balogh <[email protected]>
Signed-off-by: Peter Balogh <[email protected]>
Signed-off-by: Peter Balogh <[email protected]>
Signed-off-by: Peter Balogh <[email protected]>
func setValuesFromArgs(values []string) { | ||
if len(values) == 0 { | ||
return | ||
} | ||
for _, v := range values { | ||
key, value := splitKeyValue(v) | ||
viper.SetDefault(key, value) | ||
} | ||
} | ||
|
||
func splitKeyValue(value string) (string, string) { | ||
keyValue := strings.Split(value, "=") | ||
return keyValue[0], keyValue[1] | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd not add a separate function just for splitting a string.
func setValuesFromArgs(values []string) { | |
if len(values) == 0 { | |
return | |
} | |
for _, v := range values { | |
key, value := splitKeyValue(v) | |
viper.SetDefault(key, value) | |
} | |
} | |
func splitKeyValue(value string) (string, string) { | |
keyValue := strings.Split(value, "=") | |
return keyValue[0], keyValue[1] | |
} | |
func setValuesFromArgs(values []string) { | |
if len(values) == 0 { | |
return | |
} | |
for _, value := range values { | |
v := strings.Split(value, "=") | |
if len(v) == 2 { | |
viper.SetDefault(v[0], v[1]) | |
} else { | |
// do something here? | |
} | |
} | |
} |
type Config struct { | ||
client *backendclient.BackendClient | ||
fmConfig *families.Config | ||
scanConfigID string | ||
scanConfigName string | ||
input string | ||
asset cliconfig.Asset | ||
} | ||
|
||
func CreateConfig( | ||
client *backendclient.BackendClient, | ||
fmConfig *families.Config, | ||
scanConfigID, scanConfigName, input string, | ||
asset cliconfig.Asset, | ||
) Config { | ||
return Config{ | ||
client: client, | ||
fmConfig: fmConfig, | ||
scanConfigID: scanConfigID, | ||
scanConfigName: scanConfigName, | ||
input: input, | ||
asset: asset, | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not see the purpose of having a CreateConfig
(which should be really called NewConfig
) here. Just make the Config attributes exported.
type Config struct { | |
client *backendclient.BackendClient | |
fmConfig *families.Config | |
scanConfigID string | |
scanConfigName string | |
input string | |
asset cliconfig.Asset | |
} | |
func CreateConfig( | |
client *backendclient.BackendClient, | |
fmConfig *families.Config, | |
scanConfigID, scanConfigName, input string, | |
asset cliconfig.Asset, | |
) Config { | |
return Config{ | |
client: client, | |
fmConfig: fmConfig, | |
scanConfigID: scanConfigID, | |
scanConfigName: scanConfigName, | |
input: input, | |
asset: asset, | |
} | |
} | |
type Config struct { | |
Client *backendclient.BackendClient | |
FamiliesConfig *families.Config | |
ScanConfigID string | |
ScanConfigName string | |
Input string | |
Asset cliconfig.Asset | |
} |
Config | ||
} | ||
|
||
func newVMClarityInitiator(config Config) (*VMClarityInitiator, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
func newVMClarityInitiator(config Config) (*VMClarityInitiator, error) { | |
func New(config Config) (*VMClarityInitiator, error) { |
func createInitScanResultSummary() *models.ScanFindingsSummary { | ||
return &models.ScanFindingsSummary{ | ||
TotalExploits: utils.PointerTo(0), | ||
TotalMalware: utils.PointerTo(0), | ||
TotalMisconfigurations: utils.PointerTo(0), | ||
TotalPackages: utils.PointerTo(0), | ||
TotalRootkits: utils.PointerTo(0), | ||
TotalSecrets: utils.PointerTo(0), | ||
TotalVulnerabilities: &models.VulnerabilityScanSummary{ | ||
TotalCriticalVulnerabilities: utils.PointerTo(0), | ||
TotalHighVulnerabilities: utils.PointerTo(0), | ||
TotalMediumVulnerabilities: utils.PointerTo(0), | ||
TotalLowVulnerabilities: utils.PointerTo(0), | ||
TotalNegligibleVulnerabilities: utils.PointerTo(0), | ||
}, | ||
} | ||
} | ||
|
||
func createInitScanSummary() *models.ScanSummary { | ||
return &models.ScanSummary{ | ||
JobsCompleted: utils.PointerTo(0), | ||
JobsLeftToRun: utils.PointerTo(1), | ||
TotalExploits: utils.PointerTo(0), | ||
TotalMalware: utils.PointerTo(0), | ||
TotalMisconfigurations: utils.PointerTo(0), | ||
TotalPackages: utils.PointerTo(0), | ||
TotalRootkits: utils.PointerTo(0), | ||
TotalSecrets: utils.PointerTo(0), | ||
TotalVulnerabilities: &models.VulnerabilityScanSummary{ | ||
TotalCriticalVulnerabilities: utils.PointerTo(0), | ||
TotalHighVulnerabilities: utils.PointerTo(0), | ||
TotalMediumVulnerabilities: utils.PointerTo(0), | ||
TotalLowVulnerabilities: utils.PointerTo(0), | ||
TotalNegligibleVulnerabilities: utils.PointerTo(0), | ||
}, | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd consolidate these in api/models
package as these are used in the scanwatcher
controller as well.
type AWSInfoProvider struct{} | ||
|
||
func CreateNewAWSInfoProvider() *AWSInfoProvider { | ||
return &AWSInfoProvider{} | ||
} | ||
|
||
func (a *AWSInfoProvider) GetVMInfo() (string, string, error) { | ||
instanceIDResp, err := http.Get("http://169.254.169.254/latest/meta-data/instance-id") // nolint:noctx | ||
if err != nil { | ||
return "", "", fmt.Errorf("failed to get instance-id: %v", err) | ||
} | ||
defer instanceIDResp.Body.Close() | ||
instanceID, err := io.ReadAll(instanceIDResp.Body) | ||
if err != nil { | ||
return "", "", fmt.Errorf("failed to read instance-id response body: %v", err) | ||
} | ||
|
||
regionResp, err := http.Get("http://169.254.169.254/latest/meta-data/placement/region") // nolint:noctx | ||
if err != nil { | ||
return "", "", fmt.Errorf("failed to get region: %v", err) | ||
} | ||
defer regionResp.Body.Close() | ||
region, err := io.ReadAll(regionResp.Body) | ||
if err != nil { | ||
return "", "", fmt.Errorf("failed to read region response body: %v", err) | ||
} | ||
|
||
// cut the last character from the availability-zone in order to return only the region | ||
return string(instanceID), string(region), nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be better to add a new interface to the provider
package? Like this:
type Provider interface {
Kind() models.CloudProvider
Discoverer
Scanner
}
type Discoverer interface {
// Omitted
}
type Scanner interface {
// Omitted
}
type AssetInformer interface { // <-- new interface
AssetInfo(context.Context) (models.TargetType, error)
}
This way the provider implementations could decide if they want to implement the all the interfaces (e.g. Provider
) or just the subset of it.
Personally I avoid having interfaces related to the same infra layer scattered across different packages in the code base.
@@ -619,3 +619,34 @@ func (b *BackendClient) PostFinding(ctx context.Context, finding models.Finding) | |||
return nil, fmt.Errorf("failed to create a finding. status code=%v", resp.StatusCode()) | |||
} | |||
} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This bloats the backendclient
unnecessarily https://github.com/openclarity/vmclarity/pull/308/files#diff-189663ef212b0528411bdd1bc250e2c49471f3ae97cf265d63bf6d087212b314R623-R652
(btw, do not get having the GetScanResultSummary
either)
"github.com/openclarity/vmclarity/shared/pkg/families/vulnerabilities" | ||
) | ||
|
||
const ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these default values? If so, please add Default
prefix to their names. Otherwise these do not belong here in my opinion.
Thank you for your contribution! This PR has been automatically marked as |
implemented in: #500 |
Description
Please provide a meaningful description of what this change will do, or is for. Bonus points for including links to
related issues, other PRs, or technical references.
Note that by not including a description, you are asking reviewers to do extra work to understand the context of this
change, which may lead to your PR taking much longer to review, or result in it not being reviewed at all.
Type of Change
[ ] Bug Fix
[ ] New Feature
[ ] Breaking Change
[ ] Refactor
[ ] Documentation
[ ] Other (please describe)
Checklist