Skip to content

Commit

Permalink
Merge pull request #6929 from Checkmarx/kics-resolver-sink-uts
Browse files Browse the repository at this point in the history
update(uts): kics unit tests ramp
  • Loading branch information
gabriel-cx authored Mar 8, 2024
2 parents 2aef21f + e9f9a2d commit ab4e7c4
Show file tree
Hide file tree
Showing 9 changed files with 350 additions and 4 deletions.
4 changes: 2 additions & 2 deletions pkg/kics/resolver_sink.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func (s *Service) resolverSink(ctx context.Context, filename, scanID string, ope
resFiles, err := s.Resolver.Resolve(filename, kind)
if err != nil {
log.Err(err).Msgf("failed to render file content")
return []string{}, nil
return []string{}, err
}

for _, rfile := range resFiles.File {
Expand Down Expand Up @@ -101,7 +101,7 @@ func (s *Service) resolverSink(ctx context.Context, filename, scanID string, ope
func (s *Service) getOriginalIgnoreLines(filename string,
originalFile []uint8,
openAPIResolveReferences, isMinified bool) (ignoreLines []int, err error) {
refactor := regexp.MustCompile(`.*\n?.*KICS\_HELM\_ID.+\n`).ReplaceAll(originalFile, []uint8{})
refactor := regexp.MustCompile(`.*\n?.*KICS_HELM_ID.+\n`).ReplaceAll(originalFile, []uint8{})
refactor = regexp.MustCompile(`{{-\s*(.*?)\s*}}`).ReplaceAll(refactor, []uint8{})

documentsOriginal, err := s.Parser.Parse(filename, refactor, openAPIResolveReferences, isMinified)
Expand Down
184 changes: 184 additions & 0 deletions pkg/kics/resolver_sink_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
package kics

import (
"context"
"github.com/Checkmarx/kics/assets"
"github.com/Checkmarx/kics/internal/storage"
"github.com/Checkmarx/kics/internal/tracker"
"github.com/Checkmarx/kics/pkg/engine"
"github.com/Checkmarx/kics/pkg/engine/provider"
"github.com/Checkmarx/kics/pkg/engine/secrets"
"github.com/Checkmarx/kics/pkg/engine/source"
"github.com/Checkmarx/kics/pkg/parser"
yamlParser "github.com/Checkmarx/kics/pkg/parser/yaml"
"github.com/Checkmarx/kics/pkg/resolver"
"github.com/Checkmarx/kics/pkg/resolver/helm"
"github.com/rs/zerolog/log"
"github.com/stretchr/testify/require"
"testing"
)

func Test_ResolverSink(t *testing.T) {
ctx := context.Background()
tests := []struct {
name string
path string
service Service
expectedExcludedCount int
}{
{
name: "test resolver sink",
path: "./../../test/fixtures/helm_ignore/test",
service: MockService(
[]string{"./../../test/fixtures/helm_ignore/test"},
[]string{"Kubernetes"},
[]string{},
10,
60,
100,
ctx),
expectedExcludedCount: 11,
},
{
name: "test resolver sink no helm",
path: "./../../test/fixtures/test_scan_cloudfront_logging_disabled",
service: MockService(
[]string{"./../../test/fixtures/test_scan_cloudfront_logging_disabled"},
[]string{"CloudFormation"},
[]string{"aws"},
10,
60,
100,
ctx),
expectedExcludedCount: 0,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := tt.service

excluded, err := s.resolverSink(ctx, tt.path, "", false)
if err != nil {
t.Fatalf(`ResolverSink failed for path %s with error: %v`, tt.path, err)
}

require.Equal(t, tt.expectedExcludedCount, len(excluded))
})
}
}

func Test_ResolverSink_ParseError(t *testing.T) {
ctx := context.Background()
tests := []struct {
name string
path string
service Service
expectedErrorString string
}{
{
name: "test resolver sink",
path: "./../../test/fixtures/helm_template_parser_error/test",
service: MockService(
[]string{"./../../test/fixtures/helm_template_parser_error/test"},
[]string{"Kubernetes"},
[]string{},
10,
60,
100,
ctx),
expectedErrorString: "failed to render helm chart",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := tt.service
_, err := s.resolverSink(ctx, tt.path, "", false)
require.EqualError(t, err, tt.expectedErrorString)
})
}
}

func MockService(paths []string,
platforms []string,
cloudProviders []string,
previewLines int,
queryExecTimeout int,
maxFileSizeFlag int,
ctx context.Context) Service {

path := paths[0]

filesSource, err := provider.NewFileSystemSourceProvider(paths, []string{})
if err != nil {
log.Error().Msgf(`Failed to get File Sources for path %s with error: %v`, path, err)
}

querySource := source.NewFilesystemSource(
[]string{},
platforms,
cloudProviders,
"",
false)

combinedParser, err := parser.NewBuilder().
Add(&yamlParser.Parser{}).
Build(querySource.Types, querySource.CloudProviders)
if err != nil {
log.Error().Msgf(`Failed to build parser for path %s with error: %v`, path, err)
}

mockTracker, err := tracker.NewTracker(previewLines)
if err != nil {
log.Error().Msgf(`Failed to build tracker for path %s with error: %v`, path, err)
}

queryFilter := source.QueryInspectorParameters{}

inspector, err := engine.NewInspector(ctx,
querySource,
engine.DefaultVulnerabilityBuilder,
mockTracker,
&queryFilter,
map[string]bool{},
queryExecTimeout,
true,
1,
)
if err != nil {
log.Error().Msgf(`Failed to build inspector for path %s with error: %v`, path, err)
}

regexRulesContent := assets.SecretsQueryRegexRulesJSON

secretsInspector, err := secrets.NewInspector(
ctx,
map[string]bool{},
mockTracker,
&queryFilter,
false,
queryExecTimeout,
regexRulesContent,
false,
)
if err != nil {
log.Error().Msgf(`Failed to build secretsInspector with error: %v`, err)
}

mockResolver, err := resolver.NewBuilder().Add(&helm.Resolver{}).Build()
if err != nil {
log.Error().Msgf(`Failed to build mockResolver with error: %v`, err)
}

return Service{
SourceProvider: filesSource,
Storage: storage.NewMemoryStorage(),
Parser: combinedParser[0],
Inspector: inspector,
SecretsInspector: secretsInspector,
Tracker: mockTracker,
MaxFileSize: maxFileSizeFlag,
Resolver: mockResolver,
}
}
2 changes: 1 addition & 1 deletion pkg/resolver/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func (r *Resolver) Resolve(filePath string, kind model.FileKind) (model.Resolved
if r, ok := r.resolvers[kind]; ok {
obj, err := r.Resolve(filePath)
if err != nil {
return model.ResolvedFiles{}, nil
return model.ResolvedFiles{}, err
}
log.Debug().Msgf("resolver.Resolve() rendered file: %s", filePath)
return obj, nil
Expand Down
2 changes: 1 addition & 1 deletion pkg/scan/scan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func Test_ExecuteScan(t *testing.T) {
scanParams: Parameters{
ExcludePaths: []string{
"./../../test/fixtures/test_scan_cloudfront_logging_disabled/metadata.json",
"./../../test/fixtures/test_scan_cloudfront_logging_disabled/positive_expected_result.tf",
"./../../test/fixtures/test_scan_cloudfront_logging_disabled/test/positive_expected_result.tf",
},
Path: []string{"./../../test/fixtures/test_scan_cloudfront_logging_disabled/test/positive1.yaml"},
QueriesPath: []string{"./../../test/fixtures/test_scan_cloudfront_logging_disabled"},
Expand Down
23 changes: 23 additions & 0 deletions test/fixtures/helm_template_parser_error/test/.helmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/
24 changes: 24 additions & 0 deletions test/fixtures/helm_template_parser_error/test/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
apiVersion: v2
name: test
description: A Helm chart for Kubernetes

# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application

# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "1.16.0"
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "test.fullname" . }}
labels:
{{- include "test.labels" . | nindent 4 }}
-
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "test.selectorLabels" . | nindent 4 }}
98 changes: 98 additions & 0 deletions test/fixtures/helm_template_parser_error/test/values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Default values for test.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

replicaCount: 1

image:
repository: nginx
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: ""

imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""

serviceAccount:
# Specifies whether a service account should be created
create: true
# Automatically mount a ServiceAccount's API credentials?
automount: true
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""

podAnnotations: {}
podLabels: {}

podSecurityContext: {}
# fsGroup: 2000

securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000

service:
type: ClusterIP
port: 80

ingress:
enabled: false
className: ""
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
hosts:
- host: chart-example.local
paths:
- path: /
pathType: ImplementationSpecific
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local

resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi

autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 100
targetCPUUtilizationPercentage: 80
# targetMemoryUtilizationPercentage: 80

# Additional volumes on the output Deployment definition.
volumes: []
# - name: foo
# secret:
# secretName: mysecret
# optional: false

# Additional volumeMounts on the output Deployment definition.
volumeMounts: []
# - name: foo
# mountPath: "/etc/foo"
# readOnly: true

nodeSelector: {}

tolerations: []

affinity: {}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Some Output

0 comments on commit ab4e7c4

Please sign in to comment.