mirror of
https://github.com/kubescape/kubescape.git
synced 2026-04-15 06:58:11 +00:00
Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b772588e96 | ||
|
|
5d6ac80c38 | ||
|
|
33df0e5462 | ||
|
|
26ab049622 | ||
|
|
ac2aa764a4 | ||
|
|
d02bef62d3 | ||
|
|
46682dfe16 | ||
|
|
01c65194a8 | ||
|
|
25e42ee4b6 | ||
|
|
7e5abbdd73 | ||
|
|
56183ba369 | ||
|
|
a9c1ecd3b8 | ||
|
|
d900ce6146 | ||
|
|
3a80ff00b6 | ||
|
|
b989c4c21f | ||
|
|
65c26e22cf | ||
|
|
915fa919b2 | ||
|
|
8102dd93ba | ||
|
|
35cafa9eb4 | ||
|
|
cc823d7559 | ||
|
|
eaa74487c2 | ||
|
|
e8a4c2033f | ||
|
|
8fd9258efa | ||
|
|
159d3907b5 | ||
|
|
cde916bec8 | ||
|
|
8d289bd924 | ||
|
|
fda1c83d01 | ||
|
|
31b6a3c571 | ||
|
|
31a693e9b6 | ||
|
|
5de228ce0f | ||
|
|
ed27641f04 | ||
|
|
c7d1292c7d | ||
|
|
d8f1a25ab7 | ||
|
|
56cfb4fcef | ||
|
|
894d436274 | ||
|
|
39166d40bf |
25
.github/workflows/02-release.yaml
vendored
25
.github/workflows/02-release.yaml
vendored
@@ -41,17 +41,20 @@ jobs:
|
||||
DRAFT: false
|
||||
secrets: inherit
|
||||
|
||||
# publish-krew-plugin:
|
||||
# name: Publish Krew plugin
|
||||
# runs-on: ubuntu-latest
|
||||
# if: "${{ github.repository_owner }} == kubescape"
|
||||
# needs: create-release
|
||||
# steps:
|
||||
# - uses: actions/checkout@v3
|
||||
# with:
|
||||
# submodules: recursive
|
||||
# - name: Update new version in krew-index
|
||||
# uses: rajatjindal/krew-release-bot@v0.0.43
|
||||
publish-krew-plugin:
|
||||
name: Publish Krew plugin
|
||||
runs-on: ubuntu-latest
|
||||
if: "${{ github.repository_owner }} == kubescape"
|
||||
needs: create-release
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Update new version in krew-index
|
||||
env:
|
||||
# overriding the GITHUB_REF so the action can extract the right tag -> https://github.com/rajatjindal/krew-release-bot/blob/v0.0.43/pkg/cicd/github/actions.go#L25
|
||||
GITHUB_REF: refs/tags/${{ needs.retag.outputs.NEW_TAG }}
|
||||
uses: rajatjindal/krew-release-bot@v0.0.43
|
||||
|
||||
publish-image:
|
||||
permissions:
|
||||
|
||||
4
.github/workflows/a-pr-scanner.yaml
vendored
4
.github/workflows/a-pr-scanner.yaml
vendored
@@ -136,6 +136,10 @@ jobs:
|
||||
run: .\build.bat all
|
||||
if: matrix.os == 'windows-latest'
|
||||
|
||||
- name: Install pkg-config (macOS)
|
||||
run: brew install pkg-config
|
||||
if: matrix.os == 'macos-latest'
|
||||
|
||||
- name: Install libgit2 (Linux/macOS)
|
||||
run: make libgit2
|
||||
if: matrix.os != 'windows-latest'
|
||||
|
||||
@@ -130,6 +130,10 @@ jobs:
|
||||
run: .\build.bat all
|
||||
if: matrix.os == 'windows-latest'
|
||||
|
||||
- name: Install pkg-config (macOS)
|
||||
run: brew install pkg-config
|
||||
if: matrix.os == 'macos-latest'
|
||||
|
||||
- name: Install libgit2 (Linux/macOS)
|
||||
run: make libgit2
|
||||
if: matrix.os != 'windows-latest'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[](releases)
|
||||
[](https://github.com/kubescape/kubescape/actions/workflows/build.yaml)
|
||||
[](https://github.com/kubescape/kubescape/releases)
|
||||
[](https://github.com/kubescape/kubescape/actions/workflows/02-release.yaml)
|
||||
[](https://goreportcard.com/report/github.com/kubescape/kubescape)
|
||||
[](https://gitpod.io/#https://github.com/kubescape/kubescape)
|
||||
[](https://github.com/kubescape/kubescape/blob/master/LICENSE)
|
||||
|
||||
2
build.py
2
build.py
@@ -77,7 +77,7 @@ def main():
|
||||
|
||||
with tarfile.open(tar_file, 'w:gz') as archive:
|
||||
archive.add(ks_file, "kubescape")
|
||||
archive.add(ks_file, "LICENSE")
|
||||
archive.add("LICENSE", "LICENSE")
|
||||
|
||||
print("Build Done")
|
||||
|
||||
|
||||
@@ -106,19 +106,6 @@ func (drp *DownloadReleasedPolicy) SetRegoObjects() error {
|
||||
return drp.gs.SetRegoObjects()
|
||||
}
|
||||
|
||||
func isNativeFramework(framework string) bool {
|
||||
return contains(NativeFrameworks, framework)
|
||||
}
|
||||
|
||||
func contains(s []string, str string) bool {
|
||||
for _, v := range s {
|
||||
if strings.EqualFold(v, str) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (drp *DownloadReleasedPolicy) GetExceptions(clusterName string) ([]armotypes.PostureExceptionPolicy, error) {
|
||||
exceptions, err := drp.gs.GetSystemPostureExceptionPolicies()
|
||||
if err != nil {
|
||||
|
||||
170
core/cautils/getter/downloadreleasedpolicy_test.go
Normal file
170
core/cautils/getter/downloadreleasedpolicy_test.go
Normal file
@@ -0,0 +1,170 @@
|
||||
package getter
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestReleasedPolicy(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
p := NewDownloadReleasedPolicy()
|
||||
|
||||
t.Run("should initialize objects", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// acquire from github or from local fixture
|
||||
hydrateReleasedPolicyFromMock(t, p)
|
||||
|
||||
require.NoError(t, p.SetRegoObjects())
|
||||
|
||||
t.Run("with ListControls", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
controlIDs, err := p.ListControls()
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, controlIDs)
|
||||
|
||||
sampleSize := min(len(controlIDs), 10)
|
||||
|
||||
for _, toPin := range controlIDs[:sampleSize] {
|
||||
// Example of a returned "ID": `C-0154|Ensure_that_the_--client-cert-auth_argument_is_set_to_true|`
|
||||
controlString := toPin
|
||||
parts := strings.Split(controlString, "|")
|
||||
controlID := parts[0]
|
||||
|
||||
t.Run(fmt.Sprintf("with GetControl(%q)", controlID), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctrl, err := p.GetControl(controlID)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, ctrl)
|
||||
require.Equal(t, controlID, ctrl.ControlID)
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("with unknown GetControl()", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctrl, err := p.GetControl("zork")
|
||||
require.Error(t, err)
|
||||
require.Nil(t, ctrl)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("with GetFrameworks", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
frameworks, err := p.GetFrameworks()
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, frameworks)
|
||||
|
||||
for _, toPin := range frameworks {
|
||||
framework := toPin
|
||||
require.NotEmpty(t, framework)
|
||||
require.NotEmpty(t, framework.Name)
|
||||
|
||||
t.Run(fmt.Sprintf("with GetFramework(%q)", framework.Name), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fw, err := p.GetFramework(framework.Name)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, fw)
|
||||
|
||||
require.EqualValues(t, framework, *fw)
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("with unknown GetFramework()", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctrl, err := p.GetFramework("zork")
|
||||
require.Error(t, err)
|
||||
require.Nil(t, ctrl)
|
||||
})
|
||||
|
||||
t.Run("with ListFrameworks", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
frameworkIDs, err := p.ListFrameworks()
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, frameworkIDs)
|
||||
|
||||
require.Len(t, frameworkIDs, len(frameworks))
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
t.Run("with GetControlsInput", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
controlInputs, err := p.GetControlsInputs("") // NOTE: cluster name currently unused
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, controlInputs)
|
||||
})
|
||||
|
||||
t.Run("with GetAttackTracks", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
attackTracks, err := p.GetAttackTracks()
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, attackTracks)
|
||||
})
|
||||
|
||||
t.Run("with GetExceptions", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
exceptions, err := p.GetExceptions("") // NOTE: cluster name currently unused
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, exceptions)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a > b {
|
||||
return b
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
func hydrateReleasedPolicyFromMock(t testing.TB, p *DownloadReleasedPolicy) {
|
||||
regoFile := testRegoFile("policy")
|
||||
|
||||
if _, err := os.Stat(regoFile); errors.Is(err, fs.ErrNotExist) {
|
||||
// retrieve fixture from latest released policy from github.
|
||||
//
|
||||
// NOTE: to update the mock, just delete the testdata/policy.json file and run the tests again.
|
||||
t.Logf("updating fixture file %q from github", regoFile)
|
||||
|
||||
require.NoError(t, p.SetRegoObjects())
|
||||
require.NotNil(t, p.gs)
|
||||
|
||||
require.NoError(t,
|
||||
SaveInFile(p.gs, regoFile),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// we have a mock fixture: load this rather than calling github
|
||||
t.Logf("populating rego policy from fixture file %q", regoFile)
|
||||
buf, err := os.ReadFile(regoFile)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t,
|
||||
json.Unmarshal(buf, p.gs),
|
||||
)
|
||||
}
|
||||
|
||||
func testRegoFile(framework string) string {
|
||||
return filepath.Join(currentDir(), "testdata", fmt.Sprintf("%s.json", framework))
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
@@ -23,7 +22,7 @@ func SaveInFile(policy interface{}, pathStr string) error {
|
||||
err = os.WriteFile(pathStr, encodedData, 0644) //nolint:gosec
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
pathDir := path.Dir(pathStr)
|
||||
pathDir := filepath.Dir(pathStr)
|
||||
// pathDir could contain subdirectories
|
||||
if erm := os.MkdirAll(pathDir, 0755); erm != nil {
|
||||
return erm
|
||||
|
||||
68
core/cautils/getter/getpoliciesutils_test.go
Normal file
68
core/cautils/getter/getpoliciesutils_test.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package getter
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGetDefaultPath(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const name = "mine"
|
||||
|
||||
pth := GetDefaultPath(name)
|
||||
require.Equal(t, name, filepath.Base(pth))
|
||||
require.Equal(t, ".kubescape", filepath.Base(filepath.Dir(pth)))
|
||||
}
|
||||
|
||||
func TestSaveInFile(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dir, err := os.MkdirTemp(".", "test")
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
_ = os.RemoveAll(dir)
|
||||
}()
|
||||
|
||||
policy := map[string]interface{}{
|
||||
"key": "value",
|
||||
"number": 1.00,
|
||||
}
|
||||
|
||||
t.Run("should save data as JSON (target folder exists)", func(t *testing.T) {
|
||||
target := filepath.Join(dir, "target.json")
|
||||
require.NoError(t, SaveInFile(policy, target))
|
||||
|
||||
buf, err := os.ReadFile(target)
|
||||
require.NoError(t, err)
|
||||
var retrieved interface{}
|
||||
require.NoError(t, json.Unmarshal(buf, &retrieved))
|
||||
|
||||
require.EqualValues(t, policy, retrieved)
|
||||
})
|
||||
|
||||
t.Run("should save data as JSON (new target folder)", func(t *testing.T) {
|
||||
target := filepath.Join(dir, "subdir", "target.json")
|
||||
require.NoError(t, SaveInFile(policy, target))
|
||||
|
||||
buf, err := os.ReadFile(target)
|
||||
require.NoError(t, err)
|
||||
var retrieved interface{}
|
||||
require.NoError(t, json.Unmarshal(buf, &retrieved))
|
||||
|
||||
require.EqualValues(t, policy, retrieved)
|
||||
})
|
||||
|
||||
t.Run("should error", func(t *testing.T) {
|
||||
badPolicy := map[string]interface{}{
|
||||
"key": "value",
|
||||
"number": 1.00,
|
||||
"err": func() {},
|
||||
}
|
||||
target := filepath.Join(dir, "error.json")
|
||||
require.Error(t, SaveInFile(badPolicy, target))
|
||||
})
|
||||
}
|
||||
273
core/cautils/getter/kscloudapi_mocks_test.go
Normal file
273
core/cautils/getter/kscloudapi_mocks_test.go
Normal file
@@ -0,0 +1,273 @@
|
||||
package getter
|
||||
|
||||
import (
|
||||
"github.com/armosec/armoapi-go/armotypes"
|
||||
"github.com/kubescape/opa-utils/reporthandling"
|
||||
"github.com/kubescape/opa-utils/reporthandling/attacktrack/v1alpha1"
|
||||
)
|
||||
|
||||
func mockAttackTracks() []v1alpha1.AttackTrack {
|
||||
return []v1alpha1.AttackTrack{
|
||||
{
|
||||
ApiVersion: "v1",
|
||||
Kind: "track",
|
||||
Metadata: map[string]interface{}{"label": "name"},
|
||||
Spec: v1alpha1.AttackTrackSpecification{
|
||||
Version: "v2",
|
||||
Description: "a mock",
|
||||
Data: v1alpha1.AttackTrackStep{
|
||||
Name: "track1",
|
||||
Description: "mock-step",
|
||||
SubSteps: []v1alpha1.AttackTrackStep{
|
||||
{
|
||||
Name: "track1",
|
||||
Description: "mock-step",
|
||||
Controls: []v1alpha1.IAttackTrackControl{
|
||||
mockControlPtr("control-1"),
|
||||
},
|
||||
},
|
||||
},
|
||||
Controls: []v1alpha1.IAttackTrackControl{
|
||||
mockControlPtr("control-2"),
|
||||
mockControlPtr("control-3"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ApiVersion: "v1",
|
||||
Kind: "track",
|
||||
Metadata: map[string]interface{}{"label": "stuff"},
|
||||
Spec: v1alpha1.AttackTrackSpecification{
|
||||
Version: "v1",
|
||||
Description: "another mock",
|
||||
Data: v1alpha1.AttackTrackStep{
|
||||
Name: "track2",
|
||||
Description: "mock-step2",
|
||||
SubSteps: []v1alpha1.AttackTrackStep{
|
||||
{
|
||||
Name: "track3",
|
||||
Description: "mock-step",
|
||||
Controls: []v1alpha1.IAttackTrackControl{
|
||||
mockControlPtr("control-4"),
|
||||
},
|
||||
},
|
||||
},
|
||||
Controls: []v1alpha1.IAttackTrackControl{
|
||||
mockControlPtr("control-5"),
|
||||
mockControlPtr("control-6"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func mockFrameworks() []reporthandling.Framework {
|
||||
id1s := []string{"control-1", "control-2"}
|
||||
id2s := []string{"control-3", "control-4"}
|
||||
id3s := []string{"control-5", "control-6"}
|
||||
|
||||
return []reporthandling.Framework{
|
||||
{
|
||||
PortalBase: armotypes.PortalBase{
|
||||
Name: "mock-1",
|
||||
},
|
||||
CreationTime: "now",
|
||||
Description: "mock-1",
|
||||
Controls: []reporthandling.Control{
|
||||
mockControl("control-1"),
|
||||
mockControl("control-2"),
|
||||
},
|
||||
ControlsIDs: &id1s,
|
||||
SubSections: map[string]*reporthandling.FrameworkSubSection{
|
||||
"section1": {
|
||||
ID: "section-id",
|
||||
ControlIDs: id1s,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
PortalBase: armotypes.PortalBase{
|
||||
Name: "mock-2",
|
||||
},
|
||||
CreationTime: "then",
|
||||
Description: "mock-2",
|
||||
Controls: []reporthandling.Control{
|
||||
mockControl("control-3"),
|
||||
mockControl("control-4"),
|
||||
},
|
||||
ControlsIDs: &id2s,
|
||||
SubSections: map[string]*reporthandling.FrameworkSubSection{
|
||||
"section2": {
|
||||
ID: "section-id",
|
||||
ControlIDs: id2s,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
PortalBase: armotypes.PortalBase{
|
||||
Name: "nsa",
|
||||
},
|
||||
CreationTime: "tomorrow",
|
||||
Description: "nsa mock",
|
||||
Controls: []reporthandling.Control{
|
||||
mockControl("control-5"),
|
||||
mockControl("control-6"),
|
||||
},
|
||||
ControlsIDs: &id3s,
|
||||
SubSections: map[string]*reporthandling.FrameworkSubSection{
|
||||
"section2": {
|
||||
ID: "section-id",
|
||||
ControlIDs: id3s,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func mockControl(controlID string) reporthandling.Control {
|
||||
return reporthandling.Control{
|
||||
ControlID: controlID,
|
||||
}
|
||||
}
|
||||
func mockControlPtr(controlID string) *reporthandling.Control {
|
||||
val := mockControl(controlID)
|
||||
|
||||
return &val
|
||||
}
|
||||
|
||||
func mockExceptions() []armotypes.PostureExceptionPolicy {
|
||||
return []armotypes.PostureExceptionPolicy{
|
||||
{
|
||||
PolicyType: "postureExceptionPolicy",
|
||||
CreationTime: "now",
|
||||
Actions: []armotypes.PostureExceptionPolicyActions{
|
||||
"alertOnly",
|
||||
},
|
||||
Resources: []armotypes.PortalDesignator{
|
||||
{
|
||||
DesignatorType: "Attributes",
|
||||
Attributes: map[string]string{
|
||||
"kind": "Pod",
|
||||
"name": "coredns-[A-Za-z0-9]+-[A-Za-z0-9]+",
|
||||
"namespace": "kube-system",
|
||||
},
|
||||
},
|
||||
{
|
||||
DesignatorType: "Attributes",
|
||||
Attributes: map[string]string{
|
||||
"kind": "Pod",
|
||||
"name": "etcd-.*",
|
||||
"namespace": "kube-system",
|
||||
},
|
||||
},
|
||||
},
|
||||
PosturePolicies: []armotypes.PosturePolicy{
|
||||
{
|
||||
FrameworkName: "MITRE",
|
||||
ControlID: "C-.*",
|
||||
},
|
||||
{
|
||||
FrameworkName: "another-framework",
|
||||
ControlID: "a regexp",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
PolicyType: "postureExceptionPolicy",
|
||||
CreationTime: "then",
|
||||
Actions: []armotypes.PostureExceptionPolicyActions{
|
||||
"alertOnly",
|
||||
},
|
||||
Resources: []armotypes.PortalDesignator{
|
||||
{
|
||||
DesignatorType: "Attributes",
|
||||
Attributes: map[string]string{
|
||||
"kind": "Deployment",
|
||||
"name": "my-regexp",
|
||||
},
|
||||
},
|
||||
{
|
||||
DesignatorType: "Attributes",
|
||||
Attributes: map[string]string{
|
||||
"kind": "Secret",
|
||||
"name": "another-regexp",
|
||||
},
|
||||
},
|
||||
},
|
||||
PosturePolicies: []armotypes.PosturePolicy{
|
||||
{
|
||||
FrameworkName: "yet-another-framework",
|
||||
ControlID: "a regexp",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func mockTenantResponse() *TenantResponse {
|
||||
return &TenantResponse{
|
||||
TenantID: "id",
|
||||
Token: "token",
|
||||
Expires: "expiry-time",
|
||||
AdminMail: "admin@example.com",
|
||||
}
|
||||
}
|
||||
|
||||
func mockCustomerConfig(cluster, scope string) func() *armotypes.CustomerConfig {
|
||||
if cluster == "" {
|
||||
cluster = "my-cluster"
|
||||
}
|
||||
|
||||
if scope == "" {
|
||||
scope = "default"
|
||||
}
|
||||
|
||||
return func() *armotypes.CustomerConfig {
|
||||
return &armotypes.CustomerConfig{
|
||||
Name: "user",
|
||||
Attributes: map[string]interface{}{
|
||||
"label": "value",
|
||||
},
|
||||
Scope: armotypes.PortalDesignator{
|
||||
DesignatorType: "Attributes",
|
||||
Attributes: map[string]string{
|
||||
"kind": "Cluster",
|
||||
"name": cluster,
|
||||
"scope": scope,
|
||||
},
|
||||
},
|
||||
Settings: armotypes.Settings{
|
||||
PostureControlInputs: map[string][]string{
|
||||
"inputs-1": {"x1", "y2"},
|
||||
"inputs-2": {"x2", "y2"},
|
||||
},
|
||||
PostureScanConfig: armotypes.PostureScanConfig{
|
||||
ScanFrequency: armotypes.ScanFrequency("weekly"),
|
||||
},
|
||||
VulnerabilityScanConfig: armotypes.VulnerabilityScanConfig{
|
||||
ScanFrequency: armotypes.ScanFrequency("daily"),
|
||||
CriticalPriorityThreshold: 1,
|
||||
HighPriorityThreshold: 2,
|
||||
MediumPriorityThreshold: 3,
|
||||
ScanNewDeployment: true,
|
||||
AllowlistRegistries: []string{"a", "b"},
|
||||
BlocklistRegistries: []string{"c", "d"},
|
||||
},
|
||||
SlackConfigurations: armotypes.SlackSettings{
|
||||
Token: "slack-token",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func mockLoginResponse() *FeLoginResponse {
|
||||
return &FeLoginResponse{
|
||||
Token: "access-token",
|
||||
RefreshToken: "refresh-token",
|
||||
Expires: "expiry-time",
|
||||
ExpiresIn: 123,
|
||||
}
|
||||
}
|
||||
1096
core/cautils/getter/kscloudapi_test.go
Normal file
1096
core/cautils/getter/kscloudapi_test.go
Normal file
File diff suppressed because it is too large
Load Diff
@@ -184,3 +184,16 @@ func parseHost(host string) (string, string) {
|
||||
// default scheme
|
||||
return "https", strings.Replace(host, "https://", "", 1)
|
||||
}
|
||||
|
||||
func isNativeFramework(framework string) bool {
|
||||
return contains(NativeFrameworks, framework)
|
||||
}
|
||||
|
||||
func contains(s []string, str string) bool {
|
||||
for _, v := range s {
|
||||
if strings.EqualFold(v, str) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -386,7 +387,7 @@ func TestLoadPolicy(t *testing.T) {
|
||||
}
|
||||
|
||||
func testFrameworkFile(framework string) string {
|
||||
return filepath.Join(".", "testdata", fmt.Sprintf("%s.json", framework))
|
||||
return filepath.Join(currentDir(), "testdata", fmt.Sprintf("%s.json", framework))
|
||||
}
|
||||
|
||||
func writeTempJSONControlInputs(t testing.TB) (string, map[string][]string) {
|
||||
@@ -407,3 +408,9 @@ func writeTempJSONControlInputs(t testing.TB) (string, map[string][]string) {
|
||||
|
||||
return fileName, mock
|
||||
}
|
||||
|
||||
func currentDir() string {
|
||||
_, filename, _, _ := runtime.Caller(1)
|
||||
|
||||
return filepath.Dir(filename)
|
||||
}
|
||||
|
||||
25821
core/cautils/getter/testdata/policy.json
vendored
Normal file
25821
core/cautils/getter/testdata/policy.json
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -273,10 +273,15 @@ func getAttackTracksGetter(ctx context.Context, attackTracks, accountID string,
|
||||
|
||||
// getUIPrinter returns a printer that will be used to print to the program’s UI (terminal)
|
||||
func getUIPrinter(ctx context.Context, verboseMode bool, formatVersion string, attackTree bool, viewType cautils.ViewTypes) printer.IPrinter {
|
||||
p := printerv2.NewPrettyPrinter(verboseMode, formatVersion, attackTree, viewType)
|
||||
var p printer.IPrinter
|
||||
if helpers.ToLevel(logger.L().GetLevel()) >= helpers.WarningLevel {
|
||||
p = &printerv2.SilentPrinter{}
|
||||
} else {
|
||||
p = printerv2.NewPrettyPrinter(verboseMode, formatVersion, attackTree, viewType)
|
||||
|
||||
// Since the UI of the program is a CLI (Stdout), it means that it should always print to Stdout
|
||||
p.SetWriter(ctx, os.Stdout.Name())
|
||||
// Since the UI of the program is a CLI (Stdout), it means that it should always print to Stdout
|
||||
p.SetWriter(ctx, os.Stdout.Name())
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
@@ -5,7 +5,10 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/kubescape/v2/core/cautils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_getUIPrinter(t *testing.T) {
|
||||
@@ -14,27 +17,91 @@ func Test_getUIPrinter(t *testing.T) {
|
||||
VerboseMode: true,
|
||||
View: "control",
|
||||
}
|
||||
wantFormatVersion := scanInfo.FormatVersion
|
||||
wantVerboseMode := scanInfo.VerboseMode
|
||||
wantViewType := cautils.ViewTypes(scanInfo.View)
|
||||
|
||||
got := getUIPrinter(context.TODO(), scanInfo.VerboseMode, scanInfo.FormatVersion, scanInfo.PrintAttackTree, cautils.ViewTypes(scanInfo.View))
|
||||
|
||||
gotValue := reflect.ValueOf(got).Elem()
|
||||
gotFormatVersion := gotValue.FieldByName("formatVersion").String()
|
||||
gotVerboseMode := gotValue.FieldByName("verboseMode").Bool()
|
||||
gotViewType := cautils.ViewTypes(gotValue.FieldByName("viewType").String())
|
||||
|
||||
if gotFormatVersion != wantFormatVersion {
|
||||
t.Errorf("Got: %s, want: %s", gotFormatVersion, wantFormatVersion)
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
formatVersion string
|
||||
viewType cautils.ViewTypes
|
||||
verboseMode bool
|
||||
printAttack bool
|
||||
loggerLevel helpers.Level
|
||||
}
|
||||
type wantTypes struct {
|
||||
structType string
|
||||
formatVersion string
|
||||
viewType cautils.ViewTypes
|
||||
verboseMode bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want wantTypes
|
||||
testAllFields bool
|
||||
}{
|
||||
{
|
||||
name: "Test getUIPrinter PrettyPrinter",
|
||||
args: args{
|
||||
ctx: context.TODO(),
|
||||
verboseMode: scanInfo.VerboseMode,
|
||||
formatVersion: scanInfo.FormatVersion,
|
||||
printAttack: scanInfo.PrintAttackTree,
|
||||
viewType: cautils.ViewTypes(scanInfo.View),
|
||||
loggerLevel: helpers.InfoLevel,
|
||||
},
|
||||
want: wantTypes{
|
||||
structType: "*printer.PrettyPrinter",
|
||||
formatVersion: scanInfo.FormatVersion,
|
||||
verboseMode: scanInfo.VerboseMode,
|
||||
viewType: cautils.ViewTypes(scanInfo.View),
|
||||
},
|
||||
testAllFields: true,
|
||||
},
|
||||
{
|
||||
name: "Test getUIPrinter SilentPrinter",
|
||||
args: args{
|
||||
ctx: context.TODO(),
|
||||
verboseMode: scanInfo.VerboseMode,
|
||||
formatVersion: scanInfo.FormatVersion,
|
||||
printAttack: scanInfo.PrintAttackTree,
|
||||
viewType: cautils.ViewTypes(scanInfo.View),
|
||||
loggerLevel: helpers.WarningLevel,
|
||||
},
|
||||
want: wantTypes{
|
||||
structType: "*printer.SilentPrinter",
|
||||
formatVersion: "",
|
||||
verboseMode: false,
|
||||
viewType: cautils.ViewTypes(""),
|
||||
},
|
||||
testAllFields: false,
|
||||
},
|
||||
}
|
||||
|
||||
if gotVerboseMode != wantVerboseMode {
|
||||
t.Errorf("Got: %t, want: %t", gotVerboseMode, wantVerboseMode)
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
logger.L().SetLevel(tt.args.loggerLevel.String())
|
||||
got := getUIPrinter(tt.args.ctx, tt.args.verboseMode, tt.args.formatVersion, tt.args.printAttack, tt.args.viewType)
|
||||
|
||||
if gotViewType != wantViewType {
|
||||
t.Errorf("Got: %v, want: %v", gotViewType, wantViewType)
|
||||
}
|
||||
assert.Equal(t, tt.want.structType, reflect.TypeOf(got).String())
|
||||
|
||||
if !tt.testAllFields {
|
||||
return
|
||||
}
|
||||
|
||||
gotValue := reflect.ValueOf(got).Elem()
|
||||
gotFormatVersion := gotValue.FieldByName("formatVersion").String()
|
||||
gotVerboseMode := gotValue.FieldByName("verboseMode").Bool()
|
||||
gotViewType := cautils.ViewTypes(gotValue.FieldByName("viewType").String())
|
||||
|
||||
if gotFormatVersion != tt.want.formatVersion {
|
||||
t.Errorf("Got: %s, want: %s", gotFormatVersion, tt.want.formatVersion)
|
||||
}
|
||||
|
||||
if gotVerboseMode != tt.want.verboseMode {
|
||||
t.Errorf("Got: %t, want: %t", gotVerboseMode, tt.want.verboseMode)
|
||||
}
|
||||
|
||||
if gotViewType != tt.want.viewType {
|
||||
t.Errorf("Got: %v, want: %v", gotViewType, tt.want.viewType)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,9 +38,6 @@ spec:
|
||||
containers:
|
||||
- name: host-sensor
|
||||
image: quay.io/kubescape/host-scanner:v1.0.45
|
||||
env:
|
||||
- name: OTEL_COLLECTOR_SVC
|
||||
value: "otel-collector.kubescape:4317"
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: true
|
||||
privileged: true
|
||||
|
||||
@@ -23,7 +23,8 @@ import (
|
||||
|
||||
var (
|
||||
//go:embed hostsensor.yaml
|
||||
hostSensorYAML string
|
||||
hostSensorYAML string
|
||||
namespaceWasPresent bool
|
||||
)
|
||||
|
||||
const PortName string = "scanner"
|
||||
@@ -92,6 +93,29 @@ func (hsh *HostSensorHandler) Init(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// checkNamespaceWasPresent check if the given namespace was already present on kubernetes and in "Active" state.
|
||||
// Return true in case it find the namespace on the list, false otherwise.
|
||||
// In case we have some error with the kubernetes APIs, it returns an error.
|
||||
func (hsh *HostSensorHandler) checkNamespaceWasPresent(namespace string) bool {
|
||||
ns, err := hsh.k8sObj.KubernetesClient.
|
||||
CoreV1().
|
||||
Namespaces().
|
||||
Get(hsh.k8sObj.Context, namespace, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
// check also if it is in "Active" state.
|
||||
if ns.Status.Phase != corev1.NamespaceActive {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// namespaceWasPresent return the namespaceWasPresent variable value.
|
||||
func (hsh *HostSensorHandler) namespaceWasPresent() bool {
|
||||
return namespaceWasPresent
|
||||
}
|
||||
|
||||
func (hsh *HostSensorHandler) applyYAML(ctx context.Context) error {
|
||||
workloads, err := cautils.ReadFile([]byte(hostSensorYAML), cautils.YAML_FILE_FORMAT)
|
||||
if err != nil {
|
||||
@@ -106,6 +130,8 @@ func (hsh *HostSensorHandler) applyYAML(ctx context.Context) error {
|
||||
break
|
||||
}
|
||||
}
|
||||
// check if namespace was already present on kubernetes
|
||||
namespaceWasPresent = hsh.checkNamespaceWasPresent(namespaceName)
|
||||
|
||||
// Update workload data before applying
|
||||
for i := range workloads {
|
||||
@@ -264,7 +290,11 @@ func (hsh *HostSensorHandler) updatePodInListAtomic(ctx context.Context, eventTy
|
||||
}
|
||||
|
||||
func (hsh *HostSensorHandler) tearDownNamespace(namespace string) error {
|
||||
|
||||
// if namespace was already present on kubernetes (before installing host-scanner),
|
||||
// then we shouldn't delete it.
|
||||
if hsh.namespaceWasPresent() {
|
||||
return nil
|
||||
}
|
||||
if err := hsh.k8sObj.KubernetesClient.CoreV1().Namespaces().Delete(hsh.k8sObj.Context, namespace, metav1.DeleteOptions{GracePeriodSeconds: &hsh.gracePeriod}); err != nil {
|
||||
return fmt.Errorf("failed to delete host-sensor namespace: %v", err)
|
||||
}
|
||||
@@ -273,9 +303,11 @@ func (hsh *HostSensorHandler) tearDownNamespace(namespace string) error {
|
||||
|
||||
func (hsh *HostSensorHandler) TearDown() error {
|
||||
namespace := hsh.GetNamespace()
|
||||
// delete DaemonSet
|
||||
if err := hsh.k8sObj.KubernetesClient.AppsV1().DaemonSets(hsh.GetNamespace()).Delete(hsh.k8sObj.Context, hsh.DaemonSet.Name, metav1.DeleteOptions{GracePeriodSeconds: &hsh.gracePeriod}); err != nil {
|
||||
return fmt.Errorf("failed to delete host-sensor daemonset: %v", err)
|
||||
}
|
||||
// delete Namespace
|
||||
if err := hsh.tearDownNamespace(namespace); err != nil {
|
||||
return fmt.Errorf("failed to delete host-sensor daemonset: %v", err)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
@@ -221,6 +222,17 @@ func (hsh *HostSensorHandler) GetKubeletConfigurations(ctx context.Context) ([]h
|
||||
return res, err
|
||||
}
|
||||
|
||||
// hasCloudProviderInfo iterate over the []hostsensor.HostSensorDataEnvelope list to find info about cloud provider.
|
||||
// If information are found, ther return true. Return false otherwise.
|
||||
func hasCloudProviderInfo(cpi []hostsensor.HostSensorDataEnvelope) bool {
|
||||
for index := range cpi {
|
||||
if !reflect.DeepEqual(cpi[index].GetData(), json.RawMessage("{}\n")) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (hsh *HostSensorHandler) CollectResources(ctx context.Context) ([]hostsensor.HostSensorDataEnvelope, map[string]apis.StatusInfo, error) {
|
||||
res := make([]hostsensor.HostSensorDataEnvelope, 0)
|
||||
infoMap := make(map[string]apis.StatusInfo)
|
||||
@@ -323,18 +335,9 @@ func (hsh *HostSensorHandler) CollectResources(ctx context.Context) ([]hostsenso
|
||||
res = append(res, kcData...)
|
||||
}
|
||||
|
||||
// GetControlPlaneInfo
|
||||
kcData, err = hsh.GetControlPlaneInfo(ctx)
|
||||
if err != nil {
|
||||
addInfoToMap(ControlPlaneInfo, infoMap, err)
|
||||
logger.L().Ctx(ctx).Warning(err.Error())
|
||||
}
|
||||
if len(kcData) > 0 {
|
||||
res = append(res, kcData...)
|
||||
}
|
||||
|
||||
// GetCloudProviderInfo
|
||||
kcData, err = hsh.GetCloudProviderInfo(ctx)
|
||||
isCloudProvider := hasCloudProviderInfo(kcData)
|
||||
if err != nil {
|
||||
addInfoToMap(CloudProviderInfo, infoMap, err)
|
||||
logger.L().Ctx(ctx).Warning(err.Error())
|
||||
@@ -343,6 +346,18 @@ func (hsh *HostSensorHandler) CollectResources(ctx context.Context) ([]hostsenso
|
||||
res = append(res, kcData...)
|
||||
}
|
||||
|
||||
// GetControlPlaneInfo
|
||||
if !isCloudProvider { // we retrieve control plane info only if we are not using a cloud provider
|
||||
kcData, err = hsh.GetControlPlaneInfo(ctx)
|
||||
if err != nil {
|
||||
addInfoToMap(ControlPlaneInfo, infoMap, err)
|
||||
logger.L().Ctx(ctx).Warning(err.Error())
|
||||
}
|
||||
if len(kcData) > 0 {
|
||||
res = append(res, kcData...)
|
||||
}
|
||||
}
|
||||
|
||||
// GetCNIInfo
|
||||
kcData, err = hsh.GetCNIInfo(ctx)
|
||||
if err != nil {
|
||||
|
||||
@@ -7,15 +7,15 @@ import (
|
||||
)
|
||||
|
||||
func Test_has_signature(t *testing.T) {
|
||||
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
img string
|
||||
img string
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "valid signature",
|
||||
img: "quay.io/kubescape/gateway",
|
||||
img: "quay.io/kubescape/gateway",
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
)
|
||||
|
||||
// VerifyCommand verifies a signature on a supplied container image
|
||||
// nolint
|
||||
type VerifyCommand struct {
|
||||
options.RegistryOptions
|
||||
Annotations sigs.AnnotationsMap
|
||||
|
||||
@@ -74,6 +74,9 @@ func (opap *OPAProcessor) Process(ctx context.Context, policies *cautils.Policie
|
||||
ctx, span := otel.Tracer("").Start(ctx, "OPAProcessor.Process")
|
||||
defer span.End()
|
||||
opap.loggerStartScanning()
|
||||
defer opap.loggerDoneScanning()
|
||||
cautils.StartSpinner()
|
||||
defer cautils.StopSpinner()
|
||||
|
||||
if progressListener != nil {
|
||||
progressListener.Start(len(policies.Controls))
|
||||
@@ -109,8 +112,6 @@ func (opap *OPAProcessor) Process(ctx context.Context, policies *cautils.Policie
|
||||
|
||||
opap.Report.ReportGenerationTime = time.Now().UTC()
|
||||
|
||||
opap.loggerDoneScanning()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -7,9 +7,11 @@ import (
|
||||
"github.com/kubescape/k8s-interface/k8sinterface"
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
"github.com/kubescape/kubescape/v2/core/cautils"
|
||||
"github.com/kubescape/opa-utils/exceptions"
|
||||
"github.com/kubescape/opa-utils/reporthandling"
|
||||
"github.com/kubescape/opa-utils/reporthandling/apis"
|
||||
"github.com/kubescape/opa-utils/reporthandling/results/v1/reportsummary"
|
||||
"github.com/kubescape/opa-utils/reporthandling/results/v1/resourcesresults"
|
||||
resources "github.com/kubescape/opa-utils/resources"
|
||||
"go.opentelemetry.io/otel"
|
||||
)
|
||||
@@ -23,19 +25,27 @@ import (
|
||||
func (opap *OPAProcessor) updateResults(ctx context.Context) {
|
||||
ctx, span := otel.Tracer("").Start(ctx, "OPAProcessor.updateResults")
|
||||
defer span.End()
|
||||
|
||||
// remove data from all objects
|
||||
for i := range opap.AllResources {
|
||||
removeData(opap.AllResources[i])
|
||||
}
|
||||
|
||||
processor := exceptions.NewProcessor()
|
||||
|
||||
// set exceptions
|
||||
for i := range opap.ResourcesResult {
|
||||
|
||||
t := opap.ResourcesResult[i]
|
||||
|
||||
// first set exceptions
|
||||
// first set exceptions (reuse the same exceptions processor)
|
||||
if resource, ok := opap.AllResources[i]; ok {
|
||||
t.SetExceptions(resource, opap.Exceptions, cautils.ClusterName, opap.AllPolicies.Controls)
|
||||
t.SetExceptions(
|
||||
resource,
|
||||
opap.Exceptions,
|
||||
cautils.ClusterName,
|
||||
opap.AllPolicies.Controls, // update status depending on action required
|
||||
resourcesresults.WithExceptionsProcessor(processor),
|
||||
)
|
||||
}
|
||||
|
||||
// summarize the resources
|
||||
|
||||
@@ -72,14 +72,13 @@
|
||||
<img class="logo" src="https://raw.githubusercontent.com/kubescape/kubescape/master/core/pkg/resultshandling/printer/v2/pdf/logo.png">
|
||||
<h1>Kubescape Scan Report</h1>
|
||||
{{ with .OPASessionObj.Report.SummaryDetails }}
|
||||
<h2>By Controls</h2>
|
||||
<h3>Summary</h3>
|
||||
</br>
|
||||
<h2>Summary:</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>All</th>
|
||||
<th>Failed</th>
|
||||
<th>Excluded</th>
|
||||
<th>Skipped</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -87,19 +86,18 @@
|
||||
<tr>
|
||||
<td>{{ .NumberOfControls.All }}</td>
|
||||
<td>{{ .NumberOfControls.Failed }}</td>
|
||||
<td>{{ .NumberOfControls.Excluded }}</td>
|
||||
<td>{{ .NumberOfControls.Skipped }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Details</h3>
|
||||
</br>
|
||||
<h2>Details</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="controlSeverityCell">Severity</th>
|
||||
<th class="controlNameCell">Control Name</th>
|
||||
<th class="controlRiskCell">Failed Resources</th>
|
||||
<th class="controlRiskCell">Excluded Resources</th>
|
||||
<th class="controlRiskCell">All Resources</th>
|
||||
<th class="controlRiskCell">Risk Score, %</th>
|
||||
</tr>
|
||||
@@ -110,9 +108,8 @@
|
||||
<tr>
|
||||
<td class="controlSeverityCell">{{ controlSeverityToString $control.ScoreFactor }}</td>
|
||||
<td class="controlNameCell">{{ $control.Name }}</td>
|
||||
<td class="controlRiskCell numericCell">{{ $control.ResourceCounters.FailedResources }}</td>
|
||||
<td class="controlRiskCell numericCell">{{ $control.ResourceCounters.ExcludedResources }}</td>
|
||||
<td class="controlRiskCell numericCell">{{ sum $control.ResourceCounters.ExcludedResources $control.ResourceCounters.FailedResources $control.ResourceCounters.PassedResources }}</td>
|
||||
<td class="controlRiskCell numericCell">{{ $control.StatusCounters.FailedResources }}</td>
|
||||
<td class="controlRiskCell numericCell">{{ sum $control.StatusCounters.SkippedResources $control.StatusCounters.FailedResources $control.StatusCounters.PassedResources }}</td>
|
||||
<td class="controlRiskCell numericCell">{{ float32ToInt $control.Score }}</td>
|
||||
</tr>
|
||||
</tr>
|
||||
@@ -120,7 +117,9 @@
|
||||
<tbody>
|
||||
</table>
|
||||
{{ end }}
|
||||
<h2>By Resource</h2>
|
||||
</br>
|
||||
<h2>Failed Resources:</h2>
|
||||
</br>
|
||||
{{ $sortedResourceTableView := sortByNamespace .ResourceTableView }}
|
||||
{{ range $sortedResourceTableView }}
|
||||
<h3>Name: {{ .Resource.GetName }}</h3>
|
||||
|
||||
@@ -26,6 +26,8 @@ const (
|
||||
//go:embed html/report.gohtml
|
||||
var reportTemplate string
|
||||
|
||||
var _ printer.IPrinter = &HtmlPrinter{}
|
||||
|
||||
type HTMLReportingCtx struct {
|
||||
OPASessionObj *cautils.OPASessionObj
|
||||
ResourceTableView ResourceTableView
|
||||
|
||||
@@ -19,6 +19,8 @@ const (
|
||||
jsonOutputExt = ".json"
|
||||
)
|
||||
|
||||
var _ printer.IPrinter = &JsonPrinter{}
|
||||
|
||||
type JsonPrinter struct {
|
||||
writer *os.File
|
||||
}
|
||||
|
||||
@@ -23,10 +23,8 @@ const (
|
||||
junitOutputExt = ".xml"
|
||||
)
|
||||
|
||||
/*
|
||||
riskScore
|
||||
status
|
||||
*/
|
||||
var _ printer.IPrinter = &JunitPrinter{}
|
||||
|
||||
type JunitPrinter struct {
|
||||
writer *os.File
|
||||
verbose bool
|
||||
|
||||
@@ -32,6 +32,8 @@ var (
|
||||
kubescapeLogo []byte
|
||||
)
|
||||
|
||||
var _ printer.IPrinter = &PdfPrinter{}
|
||||
|
||||
type PdfPrinter struct {
|
||||
writer *os.File
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@ const (
|
||||
prettyPrinterOutputExt = ".txt"
|
||||
)
|
||||
|
||||
var _ printer.IPrinter = &PrettyPrinter{}
|
||||
|
||||
type PrettyPrinter struct {
|
||||
writer *os.File
|
||||
formatVersion string
|
||||
|
||||
@@ -14,6 +14,8 @@ import (
|
||||
"github.com/kubescape/opa-utils/reporthandling/results/v1/resourcesresults"
|
||||
)
|
||||
|
||||
var _ printer.IPrinter = &PrometheusPrinter{}
|
||||
|
||||
type PrometheusPrinter struct {
|
||||
writer *os.File
|
||||
verboseMode bool
|
||||
|
||||
@@ -51,6 +51,8 @@ func scoreFactorToSARIFSeverityLevel(score float32) sarifSeverityLevel {
|
||||
return sarifSeverityLevelNote
|
||||
}
|
||||
|
||||
var _ printer.IPrinter = &SARIFPrinter{}
|
||||
|
||||
// SARIFPrinter is a printer that emits the report in the SARIF format
|
||||
type SARIFPrinter struct {
|
||||
// outputFile is the name of the output file
|
||||
|
||||
@@ -1,11 +1,23 @@
|
||||
package printer
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/kubescape/kubescape/v2/core/cautils"
|
||||
"github.com/kubescape/kubescape/v2/core/pkg/resultshandling/printer"
|
||||
)
|
||||
|
||||
var _ printer.IPrinter = &SilentPrinter{}
|
||||
|
||||
// SilentPrinter is a printer that does not print anything
|
||||
type SilentPrinter struct {
|
||||
}
|
||||
|
||||
func (silentPrinter *SilentPrinter) ActionPrint(opaSessionObj *cautils.OPASessionObj) {
|
||||
func (silentPrinter *SilentPrinter) ActionPrint(ctx context.Context, opaSessionObj *cautils.OPASessionObj) {
|
||||
}
|
||||
|
||||
func (silentPrinter *SilentPrinter) SetWriter(ctx context.Context, outputFile string) {
|
||||
}
|
||||
|
||||
func (silentPrinter *SilentPrinter) Score(score float32) {
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@ import (
|
||||
|
||||
type ResultsHandler struct {
|
||||
reporterObj reporter.IReport
|
||||
printerObjs []printer.IPrinter
|
||||
uiPrinter printer.IPrinter
|
||||
scanData *cautils.OPASessionObj
|
||||
printerObjs []printer.IPrinter
|
||||
}
|
||||
|
||||
func NewResultsHandler(reporterObj reporter.IReport, printerObjs []printer.IPrinter, uiPrinter printer.IPrinter) *ResultsHandler {
|
||||
|
||||
1576
examples/output_mocks/html-format.html
Normal file
1576
examples/output_mocks/html-format.html
Normal file
File diff suppressed because it is too large
Load Diff
8
go.mod
8
go.mod
@@ -16,11 +16,11 @@ require (
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/johnfercher/maroto v0.37.0
|
||||
github.com/json-iterator/go v1.1.12
|
||||
github.com/kubescape/go-git-url v0.0.23
|
||||
github.com/kubescape/go-logger v0.0.8
|
||||
github.com/kubescape/go-git-url v0.0.24
|
||||
github.com/kubescape/go-logger v0.0.9
|
||||
github.com/kubescape/k8s-interface v0.0.99
|
||||
github.com/kubescape/opa-utils v0.0.235
|
||||
github.com/kubescape/rbac-utils v0.0.19
|
||||
github.com/kubescape/opa-utils v0.0.238
|
||||
github.com/kubescape/rbac-utils v0.0.20
|
||||
github.com/kubescape/regolibrary v1.0.250
|
||||
github.com/libgit2/git2go/v33 v33.0.9
|
||||
github.com/mattn/go-isatty v0.0.17
|
||||
|
||||
16
go.sum
16
go.sum
@@ -1084,16 +1084,16 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kubescape/go-git-url v0.0.23 h1:Xj4IPYGeqiTuIRpZf6TcRgn+T38tJE+LBQg6S4bMvj8=
|
||||
github.com/kubescape/go-git-url v0.0.23/go.mod h1:IbVT7Wsxlghsa+YxI5KOx4k9VQJaa3z0kTaQz5D3nKM=
|
||||
github.com/kubescape/go-logger v0.0.8 h1:YHC5WmOy2AegJkUeuEw93hssa5VcgM55EkzWbaPviVs=
|
||||
github.com/kubescape/go-logger v0.0.8/go.mod h1:FOCfZgMK/QC2CY1rJnzb72x29PAjjlzYmw19SUe6MEI=
|
||||
github.com/kubescape/go-git-url v0.0.24 h1:+Ryb+bA+6Kx8dBHR7nnoK7ZFvtfWkwI4exYhkhBDZUQ=
|
||||
github.com/kubescape/go-git-url v0.0.24/go.mod h1:IbVT7Wsxlghsa+YxI5KOx4k9VQJaa3z0kTaQz5D3nKM=
|
||||
github.com/kubescape/go-logger v0.0.9 h1:zkRoqgl8dwdSx+SxXtzg0A83jtAwBHcesVPWMGLBBnw=
|
||||
github.com/kubescape/go-logger v0.0.9/go.mod h1:yGiKBJ2lhq/kxzY/MVYDREL9fLV3RGD6gv+UFjslaew=
|
||||
github.com/kubescape/k8s-interface v0.0.99 h1:Bk7P694WkYPORW4c+ojpvCIQQ83Ku8durElNlvgM0Qg=
|
||||
github.com/kubescape/k8s-interface v0.0.99/go.mod h1:UO8puAwFZ3XVMlKWJj0GcdFJZI22Q7iwV+5FO6mw5FE=
|
||||
github.com/kubescape/opa-utils v0.0.235 h1:5wPoFVkFuxy3xbd9oIvDmQ+UsBUYP9cQ6J8z2guqoug=
|
||||
github.com/kubescape/opa-utils v0.0.235/go.mod h1:eAZN82Zj4GgpcQlhMox0P6s8iL5YZnWrbX+/az3UWHI=
|
||||
github.com/kubescape/rbac-utils v0.0.19 h1:7iydgVxlMLW15MgHORfMBMqNj9jHtFGACd744fdtrFs=
|
||||
github.com/kubescape/rbac-utils v0.0.19/go.mod h1:t57AhSrjuNGQ+mpZWQM/hBzrCOeKBDHegFoVo4tbikQ=
|
||||
github.com/kubescape/opa-utils v0.0.238 h1:i8uuMOi0T4Lj+svq3OlM056YFrKDt7zGAnxxqbFAnAI=
|
||||
github.com/kubescape/opa-utils v0.0.238/go.mod h1:eAZN82Zj4GgpcQlhMox0P6s8iL5YZnWrbX+/az3UWHI=
|
||||
github.com/kubescape/rbac-utils v0.0.20 h1:1MMxsCsCZ3ntDi8f9ZYYcY+K7bv50bDW5ZvnGnhMhJw=
|
||||
github.com/kubescape/rbac-utils v0.0.20/go.mod h1:t57AhSrjuNGQ+mpZWQM/hBzrCOeKBDHegFoVo4tbikQ=
|
||||
github.com/kubescape/regolibrary v1.0.250 h1:BKoH89Cex+5rsD+vn1ILxULcJ++aA/KEhV5jJ4Wgp/8=
|
||||
github.com/kubescape/regolibrary v1.0.250/go.mod h1:SQkyJbA51qjNji/1nG5jABkC0GfyZtZqDDJJB5Cczn8=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
|
||||
@@ -10,10 +10,10 @@ require (
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/gorilla/schema v1.2.0
|
||||
github.com/kubescape/go-logger v0.0.8
|
||||
github.com/kubescape/go-logger v0.0.9
|
||||
github.com/kubescape/k8s-interface v0.0.99
|
||||
github.com/kubescape/kubescape/v2 v2.0.0-00010101000000-000000000000
|
||||
github.com/kubescape/opa-utils v0.0.235
|
||||
github.com/kubescape/opa-utils v0.0.238
|
||||
github.com/stretchr/testify v1.8.1
|
||||
go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.38.0
|
||||
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448
|
||||
@@ -215,8 +215,8 @@ require (
|
||||
github.com/jung-kurt/gofpdf v1.16.2 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/klauspost/compress v1.15.11 // indirect
|
||||
github.com/kubescape/go-git-url v0.0.23 // indirect
|
||||
github.com/kubescape/rbac-utils v0.0.19 // indirect
|
||||
github.com/kubescape/go-git-url v0.0.24 // indirect
|
||||
github.com/kubescape/rbac-utils v0.0.20 // indirect
|
||||
github.com/kubescape/regolibrary v1.0.250 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/leodido/go-urn v1.2.1 // indirect
|
||||
|
||||
@@ -1089,16 +1089,16 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kubescape/go-git-url v0.0.23 h1:Xj4IPYGeqiTuIRpZf6TcRgn+T38tJE+LBQg6S4bMvj8=
|
||||
github.com/kubescape/go-git-url v0.0.23/go.mod h1:IbVT7Wsxlghsa+YxI5KOx4k9VQJaa3z0kTaQz5D3nKM=
|
||||
github.com/kubescape/go-logger v0.0.8 h1:YHC5WmOy2AegJkUeuEw93hssa5VcgM55EkzWbaPviVs=
|
||||
github.com/kubescape/go-logger v0.0.8/go.mod h1:FOCfZgMK/QC2CY1rJnzb72x29PAjjlzYmw19SUe6MEI=
|
||||
github.com/kubescape/go-git-url v0.0.24 h1:+Ryb+bA+6Kx8dBHR7nnoK7ZFvtfWkwI4exYhkhBDZUQ=
|
||||
github.com/kubescape/go-git-url v0.0.24/go.mod h1:IbVT7Wsxlghsa+YxI5KOx4k9VQJaa3z0kTaQz5D3nKM=
|
||||
github.com/kubescape/go-logger v0.0.9 h1:zkRoqgl8dwdSx+SxXtzg0A83jtAwBHcesVPWMGLBBnw=
|
||||
github.com/kubescape/go-logger v0.0.9/go.mod h1:yGiKBJ2lhq/kxzY/MVYDREL9fLV3RGD6gv+UFjslaew=
|
||||
github.com/kubescape/k8s-interface v0.0.99 h1:Bk7P694WkYPORW4c+ojpvCIQQ83Ku8durElNlvgM0Qg=
|
||||
github.com/kubescape/k8s-interface v0.0.99/go.mod h1:UO8puAwFZ3XVMlKWJj0GcdFJZI22Q7iwV+5FO6mw5FE=
|
||||
github.com/kubescape/opa-utils v0.0.235 h1:5wPoFVkFuxy3xbd9oIvDmQ+UsBUYP9cQ6J8z2guqoug=
|
||||
github.com/kubescape/opa-utils v0.0.235/go.mod h1:eAZN82Zj4GgpcQlhMox0P6s8iL5YZnWrbX+/az3UWHI=
|
||||
github.com/kubescape/rbac-utils v0.0.19 h1:7iydgVxlMLW15MgHORfMBMqNj9jHtFGACd744fdtrFs=
|
||||
github.com/kubescape/rbac-utils v0.0.19/go.mod h1:t57AhSrjuNGQ+mpZWQM/hBzrCOeKBDHegFoVo4tbikQ=
|
||||
github.com/kubescape/opa-utils v0.0.238 h1:i8uuMOi0T4Lj+svq3OlM056YFrKDt7zGAnxxqbFAnAI=
|
||||
github.com/kubescape/opa-utils v0.0.238/go.mod h1:eAZN82Zj4GgpcQlhMox0P6s8iL5YZnWrbX+/az3UWHI=
|
||||
github.com/kubescape/rbac-utils v0.0.20 h1:1MMxsCsCZ3ntDi8f9ZYYcY+K7bv50bDW5ZvnGnhMhJw=
|
||||
github.com/kubescape/rbac-utils v0.0.20/go.mod h1:t57AhSrjuNGQ+mpZWQM/hBzrCOeKBDHegFoVo4tbikQ=
|
||||
github.com/kubescape/regolibrary v1.0.250 h1:BKoH89Cex+5rsD+vn1ILxULcJ++aA/KEhV5jJ4Wgp/8=
|
||||
github.com/kubescape/regolibrary v1.0.250/go.mod h1:SQkyJbA51qjNji/1nG5jABkC0GfyZtZqDDJJB5Cczn8=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
|
||||
Reference in New Issue
Block a user