Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adds support to scan directory with all iac providers in cli mode #674

Merged

Conversation

patilpankaj212
Copy link
Contributor

@patilpankaj212 patilpankaj212 commented Apr 16, 2021

  1. all iac scan will be used when an iac type is not specified using the -i flag
  2. the scan summary will include an additional element scan_errors, which will include all the errors that occurred while the iac providers did the folder scan.
  3. scan_errors is not supported with default human readable output, also it is not part of --config-only

@codecov
Copy link

codecov bot commented Apr 18, 2021

Codecov Report

Merging #674 (c4a2787) into master (4c66c22) will increase coverage by 0.57%.
The diff coverage is 79.71%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #674      +/-   ##
==========================================
+ Coverage   73.28%   73.85%   +0.57%     
==========================================
  Files         110      110              
  Lines        3099     3175      +76     
==========================================
+ Hits         2271     2345      +74     
- Misses        650      652       +2     
  Partials      178      178              
Impacted Files Coverage Δ
pkg/iac-providers/helm/v3/load-dir.go 82.89% <44.44%> (-2.73%) ⬇️
pkg/iac-providers/kubernetes/v1/load-dir.go 67.74% <50.00%> (-4.68%) ⬇️
pkg/iac-providers/terraform/commons/load-dir.go 80.59% <50.00%> (-2.48%) ⬇️
pkg/iac-providers/kustomize/v3/load-dir.go 71.69% <55.55%> (-2.31%) ⬇️
pkg/iac-providers/output/types.go 69.56% <69.56%> (ø)
pkg/runtime/executor.go 89.28% <91.17%> (+3.13%) ⬆️
pkg/policy/opa/engine.go 71.36% <100.00%> (+5.80%) ⬆️
pkg/results/types.go 100.00% <100.00%> (ø)
pkg/runtime/validate.go 91.80% <100.00%> (+0.73%) ⬆️
pkg/cli/run.go 88.57% <0.00%> (-2.86%) ⬇️
... and 3 more

@patilpankaj212 patilpankaj212 linked an issue Apr 18, 2021 that may be closed by this pull request
resourceConfig := make(output.AllResourceConfigs)

// when dir path has value, only then it will 'all iac' scan
// when file path has value, we will go with the only iac provider in the list
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @patilpankaj212 , I wondering if we should keep the all iac scan behavior consistent between directory and file scanning?

if e.iacType == "all" {
for _, ip := range iacProvider.SupportedIacProviders() {
// skip tfplan because it doesn't support directory scanning
if ip == "tfplan" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this list also have kustomize iac type?

Comment on lines 169 to 193
// channel for directory scan response
scanRespChan := make(chan dirScanResp)

// create results output from Iac provider[s]
for _, iacP := range e.iacProviders {
go func(ip iacProvider.IacProvider) {
rc, err := ip.LoadIacDir(e.dirPath)
scanRespChan <- dirScanResp{err, rc}
}(iacP)
}

for i := 0; i < len(e.iacProviders); i++ {
sr := <-scanRespChan
merr = multierror.Append(merr, sr.err)
// deduplication of resources
if len(resourceConfig) > 0 {
for key, r := range sr.rc {
updateResourceConfigs(key, r, resourceConfig)
}
} else {
for key := range sr.rc {
resourceConfig[key] = append(resourceConfig[key], sr.rc[key]...)
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this piece of code is now eligible to be in it's own function. What do you think @patilpankaj212 ?

return results, err

// for the iac providers that don't implement sub folder scanning
// return the error (existing behavior)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be improve the comment here (existing behavior). Elaborate on the behavior rather than comment it as existing behavior

Because once this code is checked-in current behavior becomes the existing behavior.

Comment on lines 218 to 234
// channel for engine evaluation result
evalResultChan := make(chan engineEvalResult)

for _, engine := range e.policyEngines {
output, err := engine.Evaluate(policy.EngineInput{InputData: &results.ResourceConfig})
if err != nil {
return results, err
go func(eng policy.Engine) {
output, err := eng.Evaluate(policy.EngineInput{InputData: &results.ResourceConfig})
evalResultChan <- engineEvalResult{err, output}
}(engine)
}

for i := 0; i < len(e.policyEngines); i++ {
evalR := <-evalResultChan
if evalR.err != nil {
return results, evalR.err
}
violations = violations.Add(output.AsViolationStore())
violations = violations.Add(evalR.output.AsViolationStore())
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe, policy evaluation can also get it's own function.

Comment on lines 264 to 284
func updateResourceConfigs(resourceType string, resources []output.ResourceConfig, allResources output.AllResourceConfigs) {
for _, res := range resources {
if !isConfigPresent(allResources[resourceType], res) {
allResources[resourceType] = append(allResources[resourceType], res)
}
}
}

// isConfigPresent checks whether a resource is already present in the list of configs or not
// the equality of a resource is based on name, source and config of the resource
func isConfigPresent(resources []output.ResourceConfig, resourceConfig output.ResourceConfig) bool {
for _, resource := range resources {
if resource.Name == resourceConfig.Name && resource.Source == resourceConfig.Source {
if reflect.DeepEqual(resource.Config, resourceConfig.Config) {
return true
}
}
}
return false
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can these functions become part of utils? I see wider applications of the deduplication logic.

@@ -61,3 +62,25 @@ func GetResourceCount(resourceMapping map[string][]output.ResourceConfig) (count
}
return
}

// UpdateResourceConfigs adds a resource of given type if it is not present in allResources
func UpdateResourceConfigs(resourceType string, resources []output.ResourceConfig, allResources output.AllResourceConfigs) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @patilpankaj212 ,
Does it make sense to have this function and other functions in this file to be moved to the output package itself. Come to think of it these are not utils in real sense but specific use cases related to the AllResourcesConfig in the output package.

@sonarcloud
Copy link

sonarcloud bot commented Apr 30, 2021

Kudos, SonarCloud Quality Gate passed!

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 1 Code Smell

No Coverage information No Coverage information
0.0% 0.0% Duplication

@kanchwala-yusuf kanchwala-yusuf merged commit 762c561 into tenable:master Apr 30, 2021
devang-gaur pushed a commit to devang-gaur/terrascan that referenced this pull request May 5, 2021
…nable#674)

* initial changes
* fix unit tests
* run dir scan and engine evaluation concurrently
* e2e test fix
@patilpankaj212 patilpankaj212 deleted the multiple-iac-provider-scans branch May 5, 2022 11:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Enhancement: support for all iac scan for cli
2 participants