Skip to content

Commit

Permalink
Merge branch 'master' into kics-issue-6936
Browse files Browse the repository at this point in the history
  • Loading branch information
gabriel-cx authored Mar 8, 2024
2 parents 52d629d + ab4e7c4 commit 7f5a9c5
Show file tree
Hide file tree
Showing 12 changed files with 381 additions and 27 deletions.
14 changes: 7 additions & 7 deletions .github/workflows/go-ci-coverage.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go 1.21.x
uses: actions/setup-go@v4
- name: Set up Go 1.22.x
uses: actions/setup-go@v5
with:
go-version: 1.21.x
go-version: 1.22.x
- name: Run test metrics script
id: testcov
run: |
Expand All @@ -33,11 +33,11 @@ jobs:
curl -L \
https://img.shields.io/badge/Go%20Coverage-${{ steps.testcov.outputs.coverage }}%25-${{ steps.testcov.outputs.color }}.svg > coverage.svg
cat coverage.svg
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
with:
name: ${{ runner.os }}-badge-latest
path: coverage.svg
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
with:
name: ${{ runner.os }}-coverage-latest
path: coverage.html
Expand All @@ -55,12 +55,12 @@ jobs:
git config --global user.name "KICSBot"
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
- name: Download Coverage Report
uses: actions/download-artifact@master
uses: actions/download-artifact@v4
with:
name: ${{ runner.os }}-coverage-latest
path: latest-coverage
- name: Download Badge svg
uses: actions/download-artifact@master
uses: actions/download-artifact@v4
with:
name: ${{ runner.os }}-badge-latest
path: latest-coverage
Expand Down
32 changes: 17 additions & 15 deletions e2e/utils/html.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ import (
"golang.org/x/net/html"
)

var availablePlatforms = initPlatforms()
var (
availablePlatforms = initPlatforms()
severityIds = []string{"info", "low", "medium", "high", "total"}
headerIds = []string{"scan-paths", "scan-platforms"}
)

func initPlatforms() map[string]string {
platforms := make(map[string]string)
Expand All @@ -38,26 +42,24 @@ func HTMLValidation(t *testing.T, file string) {
require.NoError(t, errAct, "Opening Actual HTML File should not yield an error")

// Compare Header Data (Paths, Platforms)
headerIds := []string{"scan-paths", "scan-platforms"}
for arg := range headerIds {
expectedValue := getElementByID(expectedHTML, headerIds[arg])
actualValue := getElementByID(actualHTML, headerIds[arg])

sliceOfExpected := make([]string, 0, len(headerIds))
sliceOfActual := make([]string, 0, len(headerIds))
for _, header := range headerIds {
expectedValue := getElementByID(expectedHTML, header)
actualValue := getElementByID(actualHTML, header)
sliceOfActual = append(sliceOfActual, actualValue.LastChild.Data)
// Adapt path if running locally (dev)
if GetKICSDockerImageName() == "" {
expectedValue.LastChild.Data = KicsDevPathAdapter(expectedValue.LastChild.Data)
}

require.NotNil(t, actualValue.LastChild,
"[%s] Invalid value in Element ID <%s>", file, headerIds[arg])

require.Equal(t, expectedValue.LastChild.Data, actualValue.LastChild.Data,
"[%s] HTML Element <%s>:\n- Expected value: %s\n- Actual value: %s\n",
file, headerIds[arg], expectedValue.LastChild.Data, actualValue.LastChild.Data)
sliceOfExpected = append(sliceOfExpected, expectedValue.LastChild.Data)
require.NotNil(t, actualValue.LastChild, "[%s] Invalid value in Element ID <%s>", file, header)
}

require.ElementsMatch(t, sliceOfExpected, sliceOfActual,
"[%s] HTML Element :\n- Expected value: %s\n- Actual value: %s\n",
file, sliceOfExpected, sliceOfActual)
// Compare Severity Values (High, Medium, Total...)
severityIds := []string{"info", "low", "medium", "high", "total"}

for arg := range severityIds {
nodeIdentificator := "severity-count-" + severityIds[arg]
expectedSeverityValue := getElementByID(expectedHTML, nodeIdentificator)
Expand Down
8 changes: 7 additions & 1 deletion e2e/utils/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import (
"github.com/xeipuuv/gojsonschema"
)

var filekey = "file"

type logMsg struct {
Level string `json:"level"`
ErrorMgs string `json:"error"`
Expand Down Expand Up @@ -143,7 +145,6 @@ func CheckLine(t *testing.T, expec, want string, line int) {
}

func setFields(t *testing.T, expect, actual []string, expectFileName, actualFileName, location string) {
filekey := "file"
switch location {
case "payload":
var actualI model.Documents
Expand Down Expand Up @@ -226,6 +227,11 @@ func setFields(t *testing.T, expect, actual []string, expectFileName, actualFile
})
}

require.ElementsMatch(t, expectI.ScannedPaths, actualI.ScannedPaths,
"Expected Result content: 'fixtures/%s' doesn't match the Actual Result Scanned Paths content: 'output/%s'.",
expectFileName, actualFileName)
expectI.ScannedPaths = []string{}
actualI.ScannedPaths = []string{}
require.Equal(t, expectI, actualI,
"Expected Result content: 'fixtures/%s' doesn't match the Actual Result content: 'output/%s'.",
expectFileName, actualFileName)
Expand Down
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"
Loading

0 comments on commit 7f5a9c5

Please sign in to comment.