Compare commits

..

35 Commits

Author SHA1 Message Date
David Wertenteil
d6720b67ed fixed docker version 2022-06-19 14:40:48 +03:00
David Wertenteil
9334ad6991 fixed typo 2022-06-19 14:11:04 +03:00
David Wertenteil
7b5e4143c3 fixed test for win 2022-06-19 12:47:42 +03:00
David Wertenteil
e63e5502cd fixed test 2022-06-19 11:55:47 +03:00
David Wertenteil
154794e774 fixed test 2022-06-19 11:46:43 +03:00
David Wertenteil
4aa71725dd ignore empty file 2022-06-19 11:19:29 +03:00
David Wertenteil
9bd2e7fea4 upgrade go version 2022-06-19 09:05:32 +03:00
David Wertenteil
e6d3e7d7da fixed test 2022-06-19 08:55:56 +03:00
David Wertenteil
995f90ca53 update pkg 2022-06-16 16:41:25 +03:00
David Wertenteil
c1da380c9b fixed test 2022-06-16 12:13:55 +03:00
David Wertenteil
77f77b8c7d update opa pkg 2022-06-16 12:06:52 +03:00
David Wertenteil
b3c1aec461 fixed unitests 2022-06-15 13:43:45 +03:00
David Wertenteil
ef242b52bb adding file path to wl 2022-06-15 13:38:20 +03:00
David Wertenteil
b03a4974c4 fixed go mod 2022-06-13 15:56:46 +03:00
David Wertenteil
ca67aa7f5f fixed build files 2022-06-12 17:37:30 +03:00
David Wertenteil
11b7f6ab2f do not submit invalide account ID 2022-06-12 17:31:44 +03:00
David Wertenteil
021f2074b8 validating slice length 2022-06-12 13:54:45 +03:00
shm12
c1ba2d4b3c Added gitignore for vscode git history files 2022-06-09 16:43:49 +03:00
shm12
141ad17ece Fixed web URL in git repo scanning 2022-06-09 16:42:39 +03:00
shm12
74c81e2270 Fixed relative path in git repo scan 2022-06-09 16:42:03 +03:00
shm12
7bb124b6fe Fix backward competability of file scanning 2022-06-09 15:53:28 +03:00
shm12
8a8ff10b19 Added default pattern, and type filtering in listFiles 2022-06-09 14:55:00 +03:00
shm12
1eef32dd8e Use clone in remote git repositories 2022-06-09 14:53:48 +03:00
David Wertenteil
d7b5dd416d ignore last commit 2022-06-09 10:42:58 +03:00
David Wertenteil
536a94de45 adding git data to file 2022-06-08 16:26:02 +03:00
David Wertenteil
d8ef471eb2 support installation of a fixed version 2022-06-08 13:28:48 +03:00
David Wertenteil
ff07a80078 moved testdata repo 2022-06-07 18:10:32 +03:00
David Wertenteil
310d31a3b1 beta url support 2022-06-07 18:08:38 +03:00
David Wertenteil
8a1ef7da87 submit git scanning 2022-06-07 17:39:02 +03:00
David Wertenteil
c142779ee8 adding client build 2022-06-07 09:20:32 +03:00
David Wertenteil
640f366c7e adding grafana dashboard 2022-05-31 15:58:59 +03:00
David Wertenteil
9f36c1d6de supporting github.repository_owner 2022-05-29 08:57:56 +03:00
David Wertenteil
b3c8c078a8 Merge pull request #519 from amirmalka/dev
implemented LocalGitRepository for working with a local git folder
2022-05-29 08:43:45 +03:00
Amir Malka
5443039b8c updated commit date to time.Time and added length checking for remote URLs 2022-05-24 10:09:04 +03:00
Amir Malka
7e90956b50 implemented LocalGitRepository for working with a local git folder 2022-05-23 17:11:17 +03:00
39 changed files with 3441 additions and 901 deletions

View File

@@ -28,11 +28,11 @@ jobs:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v2
uses: actions/setup-go@v3
with:
go-version: 1.17
go-version: 1.18
# - name: Test cmd pkg
# run: cd cmd && go test -v ./...
- name: Test core pkg
@@ -46,6 +46,7 @@ jobs:
- name: Build
env:
RELEASE: v2.0.${{ github.run_number }}
CLIENT: release
ArmoBEServer: api.armo.cloud
ArmoAuthServer: auth.armo.cloud
ArmoERServer: report.armo.cloud
@@ -114,7 +115,7 @@ jobs:
run: docker login -u="${QUAY_USERNAME}" -p="${QUAY_PASSWORD}" quay.io
- name: Build the Docker image
run: docker buildx build . --file build/Dockerfile --tag ${{ steps.image-name.outputs.IMAGE_NAME }}:${{ steps.image-version.outputs.IMAGE_VERSION }} --tag ${{ steps.image-name.outputs.IMAGE_NAME }}:latest --build-arg image_version=${{ steps.image-version.outputs.IMAGE_VERSION }} --push --platform linux/amd64,linux/arm64
run: docker buildx build . --file build/Dockerfile --tag ${{ steps.image-name.outputs.IMAGE_NAME }}:${{ steps.image-version.outputs.IMAGE_VERSION }} --tag ${{ steps.image-name.outputs.IMAGE_NAME }}:latest --build-arg image_version=${{ steps.image-version.outputs.IMAGE_VERSION }} --build-arg client=image-release --push --platform linux/amd64,linux/arm64
# - name: Login to GitHub Container Registry
# uses: docker/login-action@v1

View File

@@ -11,12 +11,11 @@ jobs:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v2
uses: actions/setup-go@v3
with:
go-version: 1.17
go-version: 1.18
# - name: Test cmd pkg
# run: cd cmd && go test -v ./...
@@ -40,6 +39,7 @@ jobs:
- name: Build
env:
RELEASE: v2.0.${{ github.run_number }}
CLIENT: release-dev
ArmoBEServer: api.armo.cloud
ArmoAuthServer: auth.armo.cloud
ArmoERServer: report.armo.cloud
@@ -93,4 +93,4 @@ jobs:
run: docker login -u="${QUAY_USERNAME}" -p="${QUAY_PASSWORD}" quay.io
- name: Build the Docker image
run: docker buildx build . --file build/Dockerfile --tag ${{ steps.image-name.outputs.IMAGE_NAME }}:${{ steps.image-version.outputs.IMAGE_VERSION }} --build-arg image_version=${{ steps.image-version.outputs.IMAGE_VERSION }} --push --platform linux/amd64,linux/arm64
run: docker buildx build . --file build/Dockerfile --tag ${{ steps.image-name.outputs.IMAGE_NAME }}:${{ steps.image-version.outputs.IMAGE_VERSION }} --build-arg image_version=${{ steps.image-version.outputs.IMAGE_VERSION }} --build-arg client=image-dev --push --platform linux/amd64,linux/arm64

View File

@@ -12,12 +12,11 @@ jobs:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v2
uses: actions/setup-go@v3
with:
go-version: 1.17
go-version: 1.18
# - name: Test cmd pkg
# run: cd cmd && go test -v ./...
@@ -33,6 +32,7 @@ jobs:
- name: Build
env:
RELEASE: v2.0.${{ github.run_number }}
CLIENT: test
ArmoBEServer: api.armo.cloud
ArmoAuthServer: auth.armo.cloud
ArmoERServer: report.armo.cloud

1
.gitignore vendored
View File

@@ -4,4 +4,5 @@
*vender*
*.pyc*
.idea
.history
ca.srl

View File

@@ -28,7 +28,7 @@ Kubescape integrates natively with other DevOps tools, including Jenkins, Circle
# TL;DR
## Install:
```
```sh
curl -s https://raw.githubusercontent.com/armosec/kubescape/master/install.sh | /bin/bash
```
@@ -36,8 +36,12 @@ curl -s https://raw.githubusercontent.com/armosec/kubescape/master/install.sh |
[Install on macOS](#install-on-macos)
[Install on NixOS or Linux/macOS via nix](#install-on-nixos-or-with-nix-community)
[Install using Go](#install-using-go)
## Run:
```
```sh
kubescape scan --submit --enable-host-scan --verbose
```
@@ -101,13 +105,49 @@ Set-ExecutionPolicy RemoteSigned -scope CurrentUser
## Install on macOS
1. ```
1. ```sh
brew tap armosec/kubescape
```
2. ```
2. ```sh
brew install kubescape
```
## Install on NixOS or with nix (Community)
Direct issues installing `kubescape` via `nix` through the channels mentioned [here](https://nixos.wiki/wiki/Support)
You can use `nix` on Linux or macOS and on other platforms unofficially.
Try it out in an ephemeral shell: `nix-shell -p kubescape`
Install declarative as usual
NixOS:
```nix
# your other config ...
environment.systemPackages = with pkgs; [
# your other packages ...
kubescape
];
```
home-manager:
```nix
# your other config ...
home.packages = with pkgs; [
# your other packages ...
kubescape
];
```
Or to your profile (not preferred): `nix-env --install -A nixpkgs.kubescape`
## Install using Go
With a sufficient version of `go` you can install and build with `go install github.com/armosec/kubescape/v2@latest`
## Usage & Examples
### Examples
@@ -147,14 +187,14 @@ kubescape scan --include-namespaces development,staging,production
kubescape scan --exclude-namespaces kube-system,kube-public
```
#### Scan local `yaml`/`json` files before deploying. [Take a look at the demonstration](https://youtu.be/Ox6DaR7_4ZI)
#### Scan local `yaml`/`json` files before deploying. [Take a look at the demonstration](https://youtu.be/Ox6DaR7_4ZI) Submit the results in case the directory is a git repo. [docs](https://hub.armo.cloud/docs/repository-scanning)
```
kubescape scan *.yaml
kubescape scan *.yaml --submit
```
#### Scan kubernetes manifest files from a public github repository
#### Scan kubernetes manifest files from a git repository [and submit the results](https://hub.armo.cloud/docs/repository-scanning)
```
kubescape scan https://github.com/armosec/kubescape
kubescape scan https://github.com/armosec/kubescape --submit
```
#### Display all scanned resources (including the resources who passed)

View File

@@ -10,66 +10,68 @@ ER_SERVER_CONST = BASE_GETTER_CONST + ".ArmoERURL"
WEBSITE_CONST = BASE_GETTER_CONST + ".ArmoFEURL"
AUTH_SERVER_CONST = BASE_GETTER_CONST + ".armoAUTHURL"
def checkStatus(status, msg):
def check_status(status, msg):
if status != 0:
sys.stderr.write(msg)
exit(status)
def getBuildDir():
currentPlatform = platform.system()
buildDir = "./build/"
def get_build_dir():
current_platform = platform.system()
build_dir = "./build/"
if currentPlatform == "Windows": buildDir += "windows-latest"
elif currentPlatform == "Linux": buildDir += "ubuntu-latest"
elif currentPlatform == "Darwin": buildDir += "macos-latest"
else: raise OSError("Platform %s is not supported!" % (currentPlatform))
if current_platform == "Windows": build_dir += "windows-latest"
elif current_platform == "Linux": build_dir += "ubuntu-latest"
elif current_platform == "Darwin": build_dir += "macos-latest"
else: raise OSError("Platform %s is not supported!" % (current_platform))
return buildDir
return build_dir
def getPackageName():
packageName = "kubescape"
# if platform.system() == "Windows": packageName += ".exe"
def get_package_name():
package_name = "kubescape"
# if platform.system() == "Windows": package_name += ".exe"
return packageName
return package_name
def main():
print("Building Kubescape")
# print environment variables
# print(os.environ)
# Set some variables
packageName = getPackageName()
buildUrl = "github.com/armosec/kubescape/v2/core/cautils.BuildNumber"
releaseVersion = os.getenv("RELEASE")
ArmoBEServer = os.getenv("ArmoBEServer")
ArmoERServer = os.getenv("ArmoERServer")
ArmoWebsite = os.getenv("ArmoWebsite")
ArmoAuthServer = os.getenv("ArmoAuthServer")
package_name = get_package_name()
build_url = "github.com/armosec/kubescape/v2/core/cautils.BuildNumber"
release_version = os.getenv("RELEASE")
armo_be_server = os.getenv("ArmoBEServer")
armo_er_server = os.getenv("ArmoERServer")
armo_website = os.getenv("ArmoWebsite")
armo_auth_server = os.getenv("ArmoAuthServer")
client_var = "github.com/armosec/kubescape/v2/core/cautils.Client"
client_name = os.getenv("CLIENT")
# Create build directory
buildDir = getBuildDir()
build_dir = get_build_dir()
ks_file = os.path.join(buildDir, packageName)
ks_file = os.path.join(build_dir, package_name)
hash_file = ks_file + ".sha256"
if not os.path.isdir(buildDir):
os.makedirs(buildDir)
if not os.path.isdir(build_dir):
os.makedirs(build_dir)
# Build kubescape
ldflags = "-w -s"
if releaseVersion:
ldflags += " -X {}={}".format(buildUrl, releaseVersion)
if ArmoBEServer:
ldflags += " -X {}={}".format(BE_SERVER_CONST, ArmoBEServer)
if ArmoERServer:
ldflags += " -X {}={}".format(ER_SERVER_CONST, ArmoERServer)
if ArmoWebsite:
ldflags += " -X {}={}".format(WEBSITE_CONST, ArmoWebsite)
if ArmoAuthServer:
ldflags += " -X {}={}".format(AUTH_SERVER_CONST, ArmoAuthServer)
if release_version:
ldflags += " -X {}={}".format(build_url, release_version)
if client_name:
ldflags += " -X {}={}".format(client_var, client_name)
if armo_be_server:
ldflags += " -X {}={}".format(BE_SERVER_CONST, armo_be_server)
if armo_er_server:
ldflags += " -X {}={}".format(ER_SERVER_CONST, armo_er_server)
if armo_website:
ldflags += " -X {}={}".format(WEBSITE_CONST, armo_website)
if armo_auth_server:
ldflags += " -X {}={}".format(AUTH_SERVER_CONST, armo_auth_server)
build_command = ["go", "build", "-o", ks_file, "-ldflags" ,ldflags]
@@ -77,7 +79,7 @@ def main():
print("Build command: {}".format(" ".join(build_command)))
status = subprocess.call(build_command)
checkStatus(status, "Failed to build kubescape")
check_status(status, "Failed to build kubescape")
sha256 = hashlib.sha256()
with open(ks_file, "rb") as kube:

View File

@@ -1,9 +1,10 @@
FROM golang:1.17-alpine as builder
#ENV GOPROXY=https://goproxy.io,direct
FROM golang:1.18-alpine as builder
ARG image_version
ARG client
ENV RELEASE=$image_version
ENV CLIENT=$client
ENV GO111MODULE=

View File

@@ -72,7 +72,7 @@ func GetScanCommand(ks meta.IKubescape) *cobra.Command {
scanCmd.PersistentFlags().StringVar(&scanInfo.UseArtifactsFrom, "use-artifacts-from", "", "Load artifacts from local directory. If not used will download them")
scanCmd.PersistentFlags().StringVarP(&scanInfo.ExcludedNamespaces, "exclude-namespaces", "e", "", "Namespaces to exclude from scanning. Recommended: kube-system,kube-public")
scanCmd.PersistentFlags().Float32VarP(&scanInfo.FailThreshold, "fail-threshold", "t", 100, "Failure threshold is the percent above which the command fails and returns exit code 1")
scanCmd.PersistentFlags().StringVarP(&scanInfo.Format, "format", "f", "pretty-printer", `Output format. Supported formats: "pretty-printer","json","junit","prometheus","pdf"`)
scanCmd.PersistentFlags().StringVarP(&scanInfo.Format, "format", "f", "pretty-printer", `Output format. Supported formats: "pretty-printer", "json", "junit", "prometheus", "pdf", "html"`)
scanCmd.PersistentFlags().StringVar(&scanInfo.IncludeNamespaces, "include-namespaces", "", "scan specific namespaces. e.g: --include-namespaces ns-a,ns-b")
scanCmd.PersistentFlags().BoolVarP(&scanInfo.Local, "keep-local", "", false, "If you do not want your Kubescape results reported to ARMO backend. Use this flag if you ran with the '--submit' flag in the past and you do not want to submit your current scan results")
scanCmd.PersistentFlags().StringVarP(&scanInfo.Output, "output", "o", "", "Output file. Print output to file and not stdout")

View File

@@ -19,7 +19,7 @@ type OPASessionObj struct {
Policies []reporthandling.Framework // list of frameworks to scan
AllResources map[string]workloadinterface.IMetadata // all scanned resources, map[<rtesource ID>]<resource>
ResourcesResult map[string]resourcesresults.Result // resources scan results, map[<rtesource ID>]<resource result>
ResourceSource map[string]string // resources sources, map[<rtesource ID>]<resource result>
ResourceSource map[string]reporthandling.Source // resources sources, map[<rtesource ID>]<resource result>
PostureReport *reporthandling.PostureReport // scan results v1 - Remove
Report *reporthandlingv2.PostureReport // scan results v2 - Remove
Exceptions []armotypes.PostureExceptionPolicy // list of exceptions to apply on scan results
@@ -39,7 +39,7 @@ func NewOPASessionObj(frameworks []reporthandling.Framework, k8sResources *K8SRe
ResourcesResult: make(map[string]resourcesresults.Result),
InfoMap: make(map[string]apis.StatusInfo),
ResourceToControlsMap: make(map[string][]string),
ResourceSource: make(map[string]string),
ResourceSource: make(map[string]reporthandling.Source),
SessionID: scanInfo.ScanID,
PostureReport: &reporthandling.PostureReport{
ClusterName: ClusterName,

View File

@@ -9,8 +9,10 @@ import (
"strings"
"github.com/armosec/k8s-interface/workloadinterface"
"github.com/armosec/kubescape/v2/core/cautils/logger"
"github.com/armosec/opa-utils/objectsenvelopes"
"github.com/armosec/opa-utils/objectsenvelopes/localworkload"
"gopkg.in/yaml.v2"
)
@@ -26,8 +28,8 @@ const (
JSON_FILE_FORMAT FileFormat = "json"
)
func LoadResourcesFromFiles(inputPatterns []string) (map[string][]workloadinterface.IMetadata, error) {
files, errs := listFiles(inputPatterns)
func LoadResourcesFromFiles(input string) (map[string][]workloadinterface.IMetadata, error) {
files, errs := listFiles(input)
if len(errs) > 0 {
logger.L().Error(fmt.Sprintf("%v", errs))
}
@@ -39,6 +41,7 @@ func LoadResourcesFromFiles(inputPatterns []string) (map[string][]workloadinterf
if len(errs) > 0 {
logger.L().Error(fmt.Sprintf("%v", errs))
}
return workloads, nil
}
@@ -51,15 +54,23 @@ func loadFiles(filePaths []string) (map[string][]workloadinterface.IMetadata, []
errs = append(errs, err)
continue
}
if len(f) == 0 {
continue // empty file
}
w, e := ReadFile(f, GetFileFormat(filePaths[i]))
errs = append(errs, e...)
if w != nil {
if _, ok := workloads[filePaths[i]]; !ok {
workloads[filePaths[i]] = []workloadinterface.IMetadata{}
path := filePaths[i]
if _, ok := workloads[path]; !ok {
workloads[path] = []workloadinterface.IMetadata{}
}
wSlice := workloads[filePaths[i]]
wSlice = append(wSlice, w...)
workloads[filePaths[i]] = wSlice
wSlice := workloads[path]
for j := range w {
lw := localworkload.NewLocalWorkload(w[j].GetObject())
lw.SetPath(path)
wSlice = append(wSlice, lw)
}
workloads[path] = wSlice
}
}
return workloads, errs
@@ -68,40 +79,51 @@ func loadFiles(filePaths []string) (map[string][]workloadinterface.IMetadata, []
func loadFile(filePath string) ([]byte, error) {
return os.ReadFile(filePath)
}
func ReadFile(fileContent []byte, fileFromat FileFormat) ([]workloadinterface.IMetadata, []error) {
func ReadFile(fileContent []byte, fileFormat FileFormat) ([]workloadinterface.IMetadata, []error) {
switch fileFromat {
switch fileFormat {
case YAML_FILE_FORMAT:
return readYamlFile(fileContent)
case JSON_FILE_FORMAT:
return readJsonFile(fileContent)
default:
return nil, nil // []error{fmt.Errorf("file extension %s not supported", fileFromat)}
return nil, nil // []error{fmt.Errorf("file extension %s not supported", fileFormat)}
}
}
func listFiles(patterns []string) ([]string, []error) {
files := []string{}
// listFiles returns the list of absolute paths, full file path and list of errors. The list of abs paths and full path have the same length
func listFiles(pattern string) ([]string, []error) {
var files []string
errs := []error{}
for i := range patterns {
if strings.HasPrefix(patterns[i], "http") {
continue
}
if !filepath.IsAbs(patterns[i]) {
o, _ := os.Getwd()
patterns[i] = filepath.Join(o, patterns[i])
}
if IsFile(patterns[i]) {
files = append(files, patterns[i])
} else {
f, err := glob(filepath.Split(patterns[i])) //filepath.Glob(patterns[i])
if err != nil {
errs = append(errs, err)
} else {
files = append(files, f...)
}
}
if !filepath.IsAbs(pattern) {
o, _ := os.Getwd()
pattern = filepath.Join(o, pattern)
}
if IsFile(pattern) {
files = append(files, pattern)
return files, errs
}
root, shouldMatch := filepath.Split(pattern)
if IsDir(pattern) {
root = pattern
shouldMatch = "*"
}
if shouldMatch == "" {
shouldMatch = "*"
}
f, err := glob(root, shouldMatch)
if err != nil {
errs = append(errs, err)
} else {
files = append(files, f...)
}
return files, errs
}
@@ -194,6 +216,10 @@ func glob(root, pattern string) ([]string, error) {
if info.IsDir() {
return nil
}
fileFormat := GetFileFormat(path)
if !(fileFormat == JSON_FILE_FORMAT || fileFormat == YAML_FILE_FORMAT) {
return nil
}
if matched, err := filepath.Match(pattern, filepath.Base(path)); err != nil {
return err
} else if matched {
@@ -206,6 +232,8 @@ func glob(root, pattern string) ([]string, error) {
}
return matches, nil
}
// IsFile checks if a given path is a file
func IsFile(name string) bool {
if fi, err := os.Stat(name); err == nil {
if fi.Mode().IsRegular() {
@@ -215,6 +243,16 @@ func IsFile(name string) bool {
return false
}
// IsDir checks if a given path is a directory
func IsDir(name string) bool {
if info, err := os.Stat(name); err == nil {
if info.IsDir() {
return true
}
}
return false
}
func GetFileFormat(filePath string) FileFormat {
if IsYaml(filePath) {
return YAML_FILE_FORMAT

View File

@@ -18,13 +18,13 @@ func TestListFiles(t *testing.T) {
filesPath := onlineBoutiquePath()
files, errs := listFiles([]string{filesPath})
files, errs := listFiles(filesPath)
assert.Equal(t, 0, len(errs))
assert.Equal(t, 12, len(files))
}
func TestLoadResourcesFromFiles(t *testing.T) {
workloads, err := LoadResourcesFromFiles([]string{onlineBoutiquePath()})
workloads, err := LoadResourcesFromFiles(onlineBoutiquePath())
assert.NoError(t, err)
assert.Equal(t, 12, len(workloads))
@@ -32,33 +32,26 @@ func TestLoadResourcesFromFiles(t *testing.T) {
switch filepath.Base(i) {
case "adservice.yaml":
assert.Equal(t, 2, len(w))
assert.Equal(t, "apps/v1//Deployment/adservice", w[0].GetID())
assert.Equal(t, "/v1//Service/adservice", w[1].GetID())
assert.Equal(t, "apps/v1//Deployment/adservice", getRelativePath(w[0].GetID()))
assert.Equal(t, "/v1//Service/adservice", getRelativePath(w[1].GetID()))
}
}
}
func TestLoadFiles(t *testing.T) {
files, _ := listFiles([]string{onlineBoutiquePath()})
files, _ := listFiles(onlineBoutiquePath())
_, err := loadFiles(files)
assert.Equal(t, 0, len(err))
}
func TestLoadFile(t *testing.T) {
files, _ := listFiles([]string{strings.Replace(onlineBoutiquePath(), "*", "adservice.yaml", 1)})
files, _ := listFiles(strings.Replace(onlineBoutiquePath(), "*", "adservice.yaml", 1))
assert.Equal(t, 1, len(files))
_, err := loadFile(files[0])
assert.NoError(t, err)
}
func TestMapResources(t *testing.T) {
// policyHandler := &PolicyHandler{}
// k8sResources, err := policyHandler.loadResources(opaSessionObj.Frameworks, scanInfo)
// files, _ := listFiles([]string{onlineBoutiquePath()})
// bb, err := loadFile(files[0])
// if len(err) > 0 {
// t.Errorf("%v", err)
// }
// for i := range bb {
// t.Errorf("%s", bb[i].ToString())
// }
func getRelativePath(p string) string {
pp := strings.SplitAfter(p, "api=")
return pp[1]
}

View File

@@ -34,7 +34,7 @@ var (
armoDevERURL = "report.eudev3.cyberarmorsoft.com"
armoDevBEURL = "api-dev.armo.cloud"
armoDevFEURL = "armoui-dev.eudev3.cyberarmorsoft.com"
armoDevFEURL = "cloud-dev.armosec.io"
armoDevAUTHURL = "eggauth.eudev3.cyberarmorsoft.com"
)

View File

@@ -0,0 +1,127 @@
package cautils
import (
"fmt"
"path"
"strings"
"github.com/armosec/go-git-url/apis"
gitv5 "github.com/go-git/go-git/v5"
configv5 "github.com/go-git/go-git/v5/config"
plumbingv5 "github.com/go-git/go-git/v5/plumbing"
)
type LocalGitRepository struct {
repo *gitv5.Repository
head *plumbingv5.Reference
config *configv5.Config
}
func NewLocalGitRepository(path string) (*LocalGitRepository, error) {
gitRepo, err := gitv5.PlainOpenWithOptions(path, &gitv5.PlainOpenOptions{DetectDotGit: true})
if err != nil {
return nil, err
}
head, err := gitRepo.Head()
if err != nil {
return nil, err
}
if !head.Name().IsBranch() {
return nil, fmt.Errorf("current HEAD reference is not a branch")
}
config, err := gitRepo.Config()
if err != nil {
return nil, err
}
return &LocalGitRepository{
repo: gitRepo,
head: head,
config: config,
}, nil
}
// GetBranchName get current branch name
func (g *LocalGitRepository) GetBranchName() string {
return g.head.Name().Short()
}
// GetRemoteUrl get default remote URL
func (g *LocalGitRepository) GetRemoteUrl() (string, error) {
branchName := g.GetBranchName()
if branchRef, branchFound := g.config.Branches[branchName]; branchFound {
remoteName := branchRef.Remote
if len(g.config.Remotes[remoteName].URLs) == 0 {
return "", fmt.Errorf("expected to find URLs for remote '%s', branch '%s'", remoteName, branchName)
}
return g.config.Remotes[remoteName].URLs[0], nil
}
const defaultRemoteName string = "origin"
if len(g.config.Remotes[defaultRemoteName].URLs) == 0 {
return "", fmt.Errorf("expected to find URLs for remote '%s'", defaultRemoteName)
}
return g.config.Remotes[defaultRemoteName].URLs[0], nil
}
// GetName get origin name without the .git suffix
func (g *LocalGitRepository) GetName() (string, error) {
originUrl, err := g.GetRemoteUrl()
if err != nil {
return "", err
}
baseName := path.Base(originUrl)
// remove .git
return strings.TrimSuffix(baseName, ".git"), nil
}
// GetLastCommit get latest commit object
func (g *LocalGitRepository) GetLastCommit() (*apis.Commit, error) {
return g.GetFileLastCommit("")
}
// GetFileLastCommit get file latest commit object, if empty will return latest commit
func (g *LocalGitRepository) GetFileLastCommit(filePath string) (*apis.Commit, error) {
// By default, returns commit information from current HEAD
logOptions := &gitv5.LogOptions{}
if filePath != "" {
logOptions.FileName = &filePath
logOptions.Order = gitv5.LogOrderCommitterTime // faster -> LogOrderDFSPost
}
cIter, err := g.repo.Log(logOptions)
if err != nil {
return nil, err
}
commit, err := cIter.Next()
defer cIter.Close()
if err != nil {
return nil, err
}
return &apis.Commit{
SHA: commit.Hash.String(),
Author: apis.Committer{
Name: commit.Author.Name,
Email: commit.Author.Email,
Date: commit.Author.When,
},
Message: commit.Message,
Committer: apis.Committer{},
Files: []apis.Files{},
}, nil
}
func (g *LocalGitRepository) GetRootDir() (string, error) {
wt, err := g.repo.Worktree()
if err != nil {
return "", fmt.Errorf("failed to get repo root")
}
return wt.Filesystem.Root(), nil
}

View File

@@ -0,0 +1,155 @@
package cautils
import (
"archive/zip"
"fmt"
"io"
"os"
"path"
"path/filepath"
"strings"
"testing"
"github.com/stretchr/testify/suite"
)
type LocalGitRepositoryTestSuite struct {
suite.Suite
archive *zip.ReadCloser
gitRepositoryPath string
destinationPath string
}
func unzipFile(zipPath, destinationFolder string) (*zip.ReadCloser, error) {
archive, err := zip.OpenReader(zipPath)
if err != nil {
return nil, err
}
for _, f := range archive.File {
filePath := filepath.Join(destinationFolder, f.Name)
if !strings.HasPrefix(filePath, filepath.Clean(destinationFolder)+string(os.PathSeparator)) {
return nil, fmt.Errorf("invalid file path")
}
if f.FileInfo().IsDir() {
os.MkdirAll(filePath, os.ModePerm)
continue
}
if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {
return nil, err
}
dstFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if err != nil {
return nil, err
}
fileInArchive, err := f.Open()
if err != nil {
return nil, err
}
if _, err := io.Copy(dstFile, fileInArchive); err != nil {
return nil, err
}
dstFile.Close()
fileInArchive.Close()
}
return archive, err
}
func (s *LocalGitRepositoryTestSuite) SetupSuite() {
zippedFixturePath := path.Join(".", "testdata", "localrepo.git")
destinationPath := path.Join(".", "testdata", "temp")
gitRepositoryPath := path.Join(destinationPath, "localrepo")
os.RemoveAll(destinationPath)
archive, err := unzipFile(zippedFixturePath, destinationPath)
if err == nil {
s.archive = archive
s.gitRepositoryPath = gitRepositoryPath
s.destinationPath = destinationPath
}
}
func TestLocalGitRepositoryTestSuite(t *testing.T) {
suite.Run(t, new(LocalGitRepositoryTestSuite))
}
func (s *LocalGitRepositoryTestSuite) TearDownSuite() {
if s.archive != nil {
s.archive.Close()
}
os.RemoveAll(s.destinationPath)
}
func (s *LocalGitRepositoryTestSuite) TestInvalidRepositoryPath() {
if _, err := NewLocalGitRepository("/invalidpath"); s.Error(err) {
s.Equal("repository does not exist", err.Error())
}
}
func (s *LocalGitRepositoryTestSuite) TestGetBranchName() {
if localRepo, err := NewLocalGitRepository(s.gitRepositoryPath); s.NoError(err) {
s.Equal("master", localRepo.GetBranchName())
}
}
func (s *LocalGitRepositoryTestSuite) TestGetName() {
if localRepo, err := NewLocalGitRepository(s.gitRepositoryPath); s.NoError(err) {
if name, err := localRepo.GetName(); s.NoError(err) {
s.Equal("localrepo", name)
}
}
}
func (s *LocalGitRepositoryTestSuite) TestGetOriginUrl() {
if localRepo, err := NewLocalGitRepository(s.gitRepositoryPath); s.NoError(err) {
if url, err := localRepo.GetRemoteUrl(); s.NoError(err) {
s.Equal("git@github.com:testuser/localrepo", url)
}
}
}
func (s *LocalGitRepositoryTestSuite) TestGetLastCommit() {
if localRepo, err := NewLocalGitRepository(s.gitRepositoryPath); s.NoError(err) {
if commit, err := localRepo.GetLastCommit(); s.NoError(err) {
s.Equal("7e09312b8017695fadcd606882e3779f10a5c832", commit.SHA)
s.Equal("Amir Malka", commit.Author.Name)
s.Equal("amirm@armosec.io", commit.Author.Email)
s.Equal("2022-05-22 19:11:57 +0300 +0300", commit.Author.Date.String())
s.Equal("added file B\n", commit.Message)
}
}
}
func (s *LocalGitRepositoryTestSuite) TestGetFileLastCommit() {
s.Run("fileA", func() {
if localRepo, err := NewLocalGitRepository(s.gitRepositoryPath); s.NoError(err) {
if commit, err := localRepo.GetFileLastCommit("fileA"); s.NoError(err) {
s.Equal("9fae4be19624297947d2b605cefbff516628612d", commit.SHA)
s.Equal("Amir Malka", commit.Author.Name)
s.Equal("amirm@armosec.io", commit.Author.Email)
s.Equal("2022-05-22 18:55:48 +0300 +0300", commit.Author.Date.String())
s.Equal("added file A\n", commit.Message)
}
}
})
s.Run("fileB", func() {
if localRepo, err := NewLocalGitRepository(s.gitRepositoryPath); s.NoError(err) {
if commit, err := localRepo.GetFileLastCommit("dirA/fileB"); s.NoError(err) {
s.Equal("7e09312b8017695fadcd606882e3779f10a5c832", commit.SHA)
s.Equal("Amir Malka", commit.Author.Name)
s.Equal("amirm@armosec.io", commit.Author.Email)
s.Equal("2022-05-22 19:11:57 +0300 +0300", commit.Author.Date.String())
s.Equal("added file B\n", commit.Message)
}
}
})
}

View File

@@ -21,9 +21,23 @@ import (
"github.com/google/uuid"
)
type ScanningContext string
const (
ScanCluster string = "cluster"
ScanLocalFiles string = "yaml"
ContextCluster ScanningContext = "cluster"
ContextFile ScanningContext = "single-file"
ContextDir ScanningContext = "local-dir"
ContextGitURL ScanningContext = "git-url"
ContextGitLocal ScanningContext = "git-local"
)
const ( // deprecated
ScopeCluster = "cluster"
ScopeYAML = "yaml"
)
const (
// ScanCluster string = "cluster"
// ScanLocalFiles string = "yaml"
localControlInputsFilename string = "controls-inputs.json"
localExceptionsFilename string = "exceptions.json"
)
@@ -190,12 +204,12 @@ func (scanInfo *ScanInfo) setOutputFile() {
}
}
func (scanInfo *ScanInfo) GetScanningEnvironment() string {
if len(scanInfo.InputPatterns) != 0 {
return ScanLocalFiles
}
return ScanCluster
}
// func (scanInfo *ScanInfo) GetScanningEnvironment() string {
// if len(scanInfo.InputPatterns) != 0 {
// return ScanLocalFiles
// }
// return ScanCluster
// }
func (scanInfo *ScanInfo) SetPolicyIdentifiers(policies []string, kind apisv1.NotificationPolicyKind) {
for _, policy := range policies {
@@ -248,71 +262,176 @@ func scanInfoToScanMetadata(scanInfo *ScanInfo) *reporthandlingv2.Metadata {
metadata.ScanMetadata.VerboseMode = scanInfo.VerboseMode
metadata.ScanMetadata.ControlsInputs = scanInfo.ControlsInputs
metadata.ScanMetadata.ScanningTarget = reporthandlingv2.Cluster
if scanInfo.GetScanningEnvironment() == ScanLocalFiles {
metadata.ScanMetadata.ScanningTarget = reporthandlingv2.File
}
inputFiles := ""
if len(scanInfo.InputPatterns) > 0 {
inputFiles = scanInfo.InputPatterns[0]
}
metadata.ScanMetadata.ScanningTarget = reporthandlingv2.Cluster
if GetScanningContext(inputFiles) != ContextCluster {
metadata.ScanMetadata.ScanningTarget = reporthandlingv2.File
}
setContextMetadata(&metadata.ContextMetadata, inputFiles)
return metadata
}
func setContextMetadata(contextMetadata *reporthandlingv2.ContextMetadata, input string) {
func (scanInfo *ScanInfo) GetScanningContext() ScanningContext {
input := ""
if len(scanInfo.InputPatterns) > 0 {
input = scanInfo.InputPatterns[0]
}
return GetScanningContext(input)
}
// GetScanningContext get scanning context from the input param
func GetScanningContext(input string) ScanningContext {
// cluster
if input == "" {
contextMetadata.ClusterContextMetadata = &reporthandlingv2.ClusterMetadata{
ContextName: k8sinterface.GetContextName(),
}
return
return ContextCluster
}
// url
if gitParser, err := giturl.NewGitURL(input); err == nil {
if gitParser.GetBranch() == "" {
gitParser.SetDefaultBranch()
}
contextMetadata.RepoContextMetadata = &reporthandlingv2.RepoContextMetadata{
Repo: gitParser.GetRepo(),
Owner: gitParser.GetOwner(),
Branch: gitParser.GetBranch(),
}
return
if _, err := giturl.NewGitURL(input); err == nil {
return ContextGitURL
}
if !filepath.IsAbs(input) {
if !filepath.IsAbs(input) { // parse path
if o, err := os.Getwd(); err == nil {
input = filepath.Join(o, input)
}
}
// local git repo
if _, err := NewLocalGitRepository(input); err == nil {
return ContextGitLocal
}
// single file
if IsFile(input) {
contextMetadata.FileContextMetadata = &reporthandlingv2.FileContextMetadata{
FilePath: input,
HostName: getHostname(),
}
return
return ContextFile
}
// dir/glob
if !IsFile(input) {
return ContextDir
}
func setContextMetadata(contextMetadata *reporthandlingv2.ContextMetadata, input string) {
switch GetScanningContext(input) {
case ContextCluster:
contextMetadata.ClusterContextMetadata = &reporthandlingv2.ClusterMetadata{
ContextName: k8sinterface.GetContextName(),
}
case ContextGitURL:
// url
context, err := metadataGitURL(input)
if err != nil {
logger.L().Warning("in setContextMetadata", helpers.Interface("case", ContextGitURL), helpers.Error(err))
}
contextMetadata.RepoContextMetadata = context
case ContextDir:
contextMetadata.DirectoryContextMetadata = &reporthandlingv2.DirectoryContextMetadata{
BasePath: input,
BasePath: getAbsPath(input),
HostName: getHostname(),
}
return
case ContextFile:
contextMetadata.FileContextMetadata = &reporthandlingv2.FileContextMetadata{
FilePath: getAbsPath(input),
HostName: getHostname(),
}
case ContextGitLocal:
// local
context, err := metadataGitLocal(input)
if err != nil {
logger.L().Warning("in setContextMetadata", helpers.Interface("case", ContextGitURL), helpers.Error(err))
}
contextMetadata.RepoContextMetadata = context
}
}
func metadataGitURL(input string) (*reporthandlingv2.RepoContextMetadata, error) {
context := &reporthandlingv2.RepoContextMetadata{}
gitParser, err := giturl.NewGitAPI(input)
if err != nil {
return context, fmt.Errorf("%w", err)
}
if gitParser.GetBranchName() == "" {
gitParser.SetDefaultBranchName()
}
context.Provider = gitParser.GetProvider()
context.Repo = gitParser.GetRepoName()
context.Owner = gitParser.GetOwnerName()
context.Branch = gitParser.GetBranchName()
context.RemoteURL = gitParser.GetURL().String()
commit, err := gitParser.GetLatestCommit()
if err != nil {
return context, fmt.Errorf("%w", err)
}
context.LastCommit = reporthandling.LastCommit{
Hash: commit.SHA,
Date: commit.Committer.Date,
CommitterName: commit.Committer.Name,
}
return context, nil
}
func metadataGitLocal(input string) (*reporthandlingv2.RepoContextMetadata, error) {
gitParser, err := NewLocalGitRepository(input)
if err != nil {
return nil, fmt.Errorf("%w", err)
}
remoteURL, err := gitParser.GetRemoteUrl()
if err != nil {
return nil, fmt.Errorf("%w", err)
}
context := &reporthandlingv2.RepoContextMetadata{}
gitParserURL, err := giturl.NewGitURL(remoteURL)
if err != nil {
return context, fmt.Errorf("%w", err)
}
gitParserURL.SetBranchName(gitParser.GetBranchName())
context.Provider = gitParserURL.GetProvider()
context.Repo = gitParserURL.GetRepoName()
context.Owner = gitParserURL.GetOwnerName()
context.Branch = gitParserURL.GetBranchName()
context.RemoteURL = gitParserURL.GetURL().String()
commit, err := gitParser.GetLastCommit()
if err != nil {
return context, fmt.Errorf("%w", err)
}
context.LastCommit = reporthandling.LastCommit{
Hash: commit.SHA,
Date: commit.Committer.Date,
CommitterName: commit.Committer.Name,
}
return context, nil
}
func getHostname() string {
if h, e := os.Hostname(); e == nil {
return h
}
return ""
}
func getAbsPath(p string) string {
if !filepath.IsAbs(p) { // parse path
if o, err := os.Getwd(); err == nil {
return filepath.Join(o, p)
}
}
return p
}
// ScanningContextToScanningScope convert the context to the deprecated scope
func ScanningContextToScanningScope(scanningContext ScanningContext) string {
if scanningContext == ContextCluster {
return ScopeCluster
}
return ScopeYAML
}

View File

@@ -18,34 +18,6 @@ func TestSetContextMetadata(t *testing.T) {
assert.Nil(t, ctx.HelmContextMetadata)
assert.Nil(t, ctx.RepoContextMetadata)
}
{
ctx := reporthandlingv2.ContextMetadata{}
setContextMetadata(&ctx, "file")
assert.Nil(t, ctx.ClusterContextMetadata)
assert.NotNil(t, ctx.DirectoryContextMetadata)
assert.Nil(t, ctx.FileContextMetadata)
assert.Nil(t, ctx.HelmContextMetadata)
assert.Nil(t, ctx.RepoContextMetadata)
hostName := getHostname()
assert.Contains(t, ctx.DirectoryContextMetadata.BasePath, "file")
assert.Equal(t, hostName, ctx.DirectoryContextMetadata.HostName)
}
{
ctx := reporthandlingv2.ContextMetadata{}
setContextMetadata(&ctx, "scaninfo_test.go")
assert.Nil(t, ctx.ClusterContextMetadata)
assert.Nil(t, ctx.DirectoryContextMetadata)
assert.NotNil(t, ctx.FileContextMetadata)
assert.Nil(t, ctx.HelmContextMetadata)
assert.Nil(t, ctx.RepoContextMetadata)
hostName := getHostname()
assert.Contains(t, ctx.FileContextMetadata.FilePath, "scaninfo_test.go")
assert.Equal(t, hostName, ctx.FileContextMetadata.HostName)
}
{
ctx := reporthandlingv2.ContextMetadata{}
setContextMetadata(&ctx, "https://github.com/armosec/kubescape")
@@ -65,3 +37,11 @@ func TestSetContextMetadata(t *testing.T) {
func TestGetHostname(t *testing.T) {
assert.NotEqual(t, "", getHostname())
}
func TestGetScanningContext(t *testing.T) {
assert.Equal(t, ContextCluster, GetScanningContext(""))
// assert.Equal(t, ContextDir, GetScanningContext("/"))
assert.Equal(t, ContextGitURL, GetScanningContext("https://github.com/armosec/kubescape"))
// assert.Equal(t, ContextFile, GetScanningContext(path.Join(".", "testdata", "localrepo.git")))
// assert.Equal(t, ContextGitLocal, GetScanningContext(path.Join(".", "testdata")))
}

BIN
core/cautils/testdata/localrepo.git vendored Normal file

Binary file not shown.

View File

@@ -17,6 +17,7 @@ const SKIP_VERSION_CHECK_DEPRECATED = "KUBESCAPE_SKIP_UPDATE_CHECK"
const SKIP_VERSION_CHECK = "KS_SKIP_UPDATE_CHECK"
var BuildNumber string
var Client string
const UnknownBuildNumber = "unknown"
@@ -48,10 +49,12 @@ type VersionCheckHandler struct {
}
type VersionCheckRequest struct {
Client string `json:"client"` // kubescape
ClientBuild string `json:"clientBuild"` // client build environment
ClientVersion string `json:"clientVersion"` // kubescape version
Framework string `json:"framework"` // framework name
FrameworkVersion string `json:"frameworkVersion"` // framework version
ScanningTarget string `json:"target"` // scanning target- cluster/yaml
ScanningTarget string `json:"target"` // Deprecated
ScanningContext string `json:"context"` // scanning context- cluster/file/gitURL/localGit/dir
}
type VersionCheckResponse struct {
@@ -74,8 +77,12 @@ func NewVersionCheckRequest(buildNumber, frameworkName, frameworkVersion, scanni
if scanningTarget == "" {
scanningTarget = "unknown"
}
if Client == "" {
Client = "local-build"
}
return &VersionCheckRequest{
Client: "kubescape",
ClientBuild: Client,
ClientVersion: buildNumber,
Framework: frameworkName,
FrameworkVersion: frameworkVersion,

View File

@@ -12,6 +12,7 @@ import (
"github.com/armosec/kubescape/v2/core/pkg/resourcehandler"
"github.com/armosec/kubescape/v2/core/pkg/resultshandling/reporter"
reporterv2 "github.com/armosec/kubescape/v2/core/pkg/resultshandling/reporter/v2"
"github.com/google/uuid"
"github.com/armosec/rbac-utils/rbacscanner"
)
@@ -122,7 +123,6 @@ func policyIdentifierNames(pi []cautils.PolicyIdentifier) string {
func setSubmitBehavior(scanInfo *cautils.ScanInfo, tenantConfig cautils.ITenantConfig) {
/*
If "First run (local config not found)" -
Default/keep-local - Do not send report
Submit - Create tenant & Submit report
@@ -139,8 +139,20 @@ func setSubmitBehavior(scanInfo *cautils.ScanInfo, tenantConfig cautils.ITenantC
return
}
scanningContext := scanInfo.GetScanningContext()
if scanningContext == cautils.ContextFile || scanningContext == cautils.ContextDir {
scanInfo.Submit = false
return
}
if tenantConfig.IsConfigFound() { // config found in cache (submitted)
if !scanInfo.Local {
if tenantConfig.GetAccountID() != "" {
if _, err := uuid.Parse(tenantConfig.GetAccountID()); err != nil {
scanInfo.Submit = false
return
}
}
// Submit report
scanInfo.Submit = true
}
@@ -164,20 +176,6 @@ func getPolicyGetter(loadPoliciesFromFile []string, tennatEmail string, framewor
}
// func setGetArmoAPIConnector(scanInfo *cautils.ScanInfo, customerGUID string) {
// g := getter.GetArmoAPIConnector() // download policy from ARMO backend
// g.SetCustomerGUID(customerGUID)
// scanInfo.PolicyGetter = g
// if scanInfo.ScanAll {
// frameworks, err := g.ListCustomFrameworks(customerGUID)
// if err != nil {
// glog.Error("failed to get custom frameworks") // handle error
// return
// }
// scanInfo.SetPolicyIdentifiers(frameworks, reporthandling.KindFramework)
// }
// }
// setConfigInputsGetter sets the config input getter - local file/github release/ArmoAPI
func getConfigInputsGetter(ControlsInputs string, accountID string, downloadReleasedPolicy *getter.DownloadReleasedPolicy) getter.IControlsInputsGetter {
if len(ControlsInputs) > 0 {

View File

@@ -34,7 +34,7 @@ func getInterfaces(scanInfo *cautils.ScanInfo) componentInterfaces {
// ================== setup k8s interface object ======================================
var k8s *k8sinterface.KubernetesApi
if scanInfo.GetScanningEnvironment() == cautils.ScanCluster {
if scanInfo.GetScanningContext() == cautils.ContextCluster {
k8s = getKubernetesApi()
if k8s == nil {
logger.L().Fatal("failed connecting to Kubernetes cluster")
@@ -48,11 +48,6 @@ func getInterfaces(scanInfo *cautils.ScanInfo) componentInterfaces {
// Set submit behavior AFTER loading tenant config
setSubmitBehavior(scanInfo, tenantConfig)
// Do not submit yaml scanning
if len(scanInfo.InputPatterns) > 0 {
scanInfo.Submit = false
}
if scanInfo.Submit {
// submit - Create tenant & Submit report
if err := tenantConfig.SetTenant(); err != nil {
@@ -63,7 +58,7 @@ func getInterfaces(scanInfo *cautils.ScanInfo) componentInterfaces {
// ================== version testing ======================================
v := cautils.NewIVersionCheckHandler()
v.CheckLatestVersion(cautils.NewVersionCheckRequest(cautils.BuildNumber, policyIdentifierNames(scanInfo.PolicyIdentifier), "", scanInfo.GetScanningEnvironment()))
v.CheckLatestVersion(cautils.NewVersionCheckRequest(cautils.BuildNumber, policyIdentifierNames(scanInfo.PolicyIdentifier), "", cautils.ScanningContextToScanningScope(scanInfo.GetScanningContext())))
// ================== setup host scanner object ======================================
@@ -154,7 +149,7 @@ func (ks *Kubescape) Scan(scanInfo *cautils.ScanInfo) (*resultshandling.ResultsH
reportResults := opaprocessor.NewOPAProcessor(scanData, deps)
if err := reportResults.ProcessRulesListenner(); err != nil {
// TODO - do something
return resultsHandling, err
return resultsHandling, fmt.Errorf("%w", err)
}
// ========================= results handling =====================
@@ -166,25 +161,3 @@ func (ks *Kubescape) Scan(scanInfo *cautils.ScanInfo) (*resultshandling.ResultsH
return resultsHandling, nil
}
// func askUserForHostSensor() bool {
// return false
// if !isatty.IsTerminal(os.Stdin.Fd()) {
// return false
// }
// if ssss, err := os.Stdin.Stat(); err == nil {
// // fmt.Printf("Found stdin type: %s\n", ssss.Mode().Type())
// if ssss.Mode().Type()&(fs.ModeDevice|fs.ModeCharDevice) > 0 { //has TTY
// fmt.Fprintf(os.Stderr, "Would you like to scan K8s nodes? [y/N]. This is required to collect valuable data for certain controls\n")
// fmt.Fprintf(os.Stderr, "Use --enable-host-scan flag to suppress this message\n")
// var b []byte = make([]byte, 1)
// if n, err := os.Stdin.Read(b); err == nil {
// if n > 0 && len(b) > 0 && (b[0] == 'y' || b[0] == 'Y') {
// return true
// }
// }
// }
// }
// return false
// }

View File

@@ -2,9 +2,13 @@ package resourcehandler
import (
"fmt"
"os"
"path/filepath"
"github.com/armosec/armoapi-go/armotypes"
giturl "github.com/armosec/go-git-url"
"github.com/armosec/k8s-interface/workloadinterface"
"github.com/armosec/opa-utils/reporthandling"
"k8s.io/apimachinery/pkg/version"
"github.com/armosec/k8s-interface/k8sinterface"
@@ -33,35 +37,59 @@ func (fileHandler *FileResourceHandler) GetResources(sessionObj *cautils.OPASess
// map resources based on framework required resources: map["/group/version/kind"][]<k8s workloads ids>
k8sResources := setK8sResourceMap(sessionObj.Policies)
allResources := map[string]workloadinterface.IMetadata{}
workloadIDToSource := make(map[string]string, 0)
workloadIDToSource := make(map[string]reporthandling.Source, 0)
armoResources := &cautils.ArmoResources{}
workloads := []workloadinterface.IMetadata{}
if len(fileHandler.inputPatterns) == 0 {
return nil, nil, nil, fmt.Errorf("missing input")
}
path := fileHandler.inputPatterns[0]
// Clone git repository if needed
gitURL, err := giturl.NewGitURL(path)
if err == nil {
logger.L().Info("cloning", helpers.String("repository url", gitURL.GetURL().String()))
cautils.StartSpinner()
cloneDir, err := cloneRepo(gitURL)
cautils.StopSpinner()
if err != nil {
return nil, allResources, nil, fmt.Errorf("failed to clone git repo '%s', %w", gitURL.GetURL().String(), err)
}
defer os.RemoveAll(cloneDir)
path = filepath.Join(cloneDir, gitURL.GetPath())
}
// load resource from local file system
sourceToWorkloads, err := cautils.LoadResourcesFromFiles(fileHandler.inputPatterns)
logger.L().Info("Accessing local objects")
sourceToWorkloads, err := cautils.LoadResourcesFromFiles(path)
if err != nil {
return nil, allResources, nil, err
}
// Get repo root
repoRoot := ""
giRepo, err := cautils.NewLocalGitRepository(path)
if err == nil {
repoRoot, _ = giRepo.GetRootDir()
}
for source, ws := range sourceToWorkloads {
workloads = append(workloads, ws...)
relSource, err := filepath.Rel(repoRoot, source)
if err == nil {
source = relSource
}
for i := range ws {
workloadIDToSource[ws[i].GetID()] = source
workloadIDToSource[ws[i].GetID()] = reporthandling.Source{RelativePath: source}
}
}
logger.L().Debug("files found in local storage", helpers.Int("files", len(sourceToWorkloads)), helpers.Int("workloads", len(workloads)))
// load resources from url
sourceToWorkloads, err = loadResourcesFromUrl(fileHandler.inputPatterns)
if err != nil {
return nil, allResources, nil, err
}
for source, ws := range sourceToWorkloads {
workloads = append(workloads, ws...)
for i := range ws {
workloadIDToSource[ws[i].GetID()] = source
}
}
// addCommitData(fileHandler.inputPatterns[0], workloadIDToSource)
if len(workloads) == 0 {
return nil, allResources, nil, fmt.Errorf("empty list of workloads - no workloads found")
@@ -70,7 +98,7 @@ func (fileHandler *FileResourceHandler) GetResources(sessionObj *cautils.OPASess
sessionObj.ResourceSource = workloadIDToSource
// map all resources: map["/group/version/kind"][]<k8s workloads>
// map all resources: map["/apiVersion/version/kind"][]<k8s workloads>
mappedResources := mapResources(workloads)
// save only relevant resources
@@ -89,8 +117,9 @@ func (fileHandler *FileResourceHandler) GetResources(sessionObj *cautils.OPASess
logger.L().Warning("failed to collect images vulnerabilities", helpers.Error(err))
}
return k8sResources, allResources, armoResources, nil
logger.L().Success("Accessed to local objects")
return k8sResources, allResources, armoResources, nil
}
func (fileHandler *FileResourceHandler) GetClusterAPIServerInfo() *version.Info {
@@ -125,3 +154,25 @@ func mapResources(workloads []workloadinterface.IMetadata) map[string][]workload
return allResources
}
func addCommitData(input string, workloadIDToSource map[string]reporthandling.Source) {
giRepo, err := cautils.NewLocalGitRepository(input)
if err != nil {
return
}
for k := range workloadIDToSource {
sourceObj := workloadIDToSource[k]
lastCommit, err := giRepo.GetFileLastCommit(sourceObj.RelativePath)
if err != nil {
continue
}
sourceObj.LastCommit = reporthandling.LastCommit{
Hash: lastCommit.SHA,
Date: lastCommit.Author.Date,
CommitterName: lastCommit.Author.Name,
CommitterEmail: lastCommit.Author.Email,
Message: lastCommit.Message,
}
workloadIDToSource[k] = sourceObj
}
}

View File

@@ -0,0 +1,36 @@
package resourcehandler
import (
"fmt"
"os"
giturl "github.com/armosec/go-git-url"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
)
// cloneRepo clones a repository to a local temporary directory and returns the directory
func cloneRepo(gitURL giturl.IGitURL) (string, error) {
// Create temp directory
tmpDir, err := os.MkdirTemp("", "")
if err != nil {
return "", fmt.Errorf("failed to create temporary directory: %w", err)
}
// Clone option
cloneURL := gitURL.GetHttpCloneURL()
cloneOpts := git.CloneOptions{URL: cloneURL}
if gitURL.GetBranchName() != "" {
cloneOpts.ReferenceName = plumbing.NewBranchReferenceName(gitURL.GetBranchName())
cloneOpts.SingleBranch = true
}
// Actual clone
_, err = git.PlainClone(tmpDir, false, &cloneOpts)
if err != nil {
return "", fmt.Errorf("failed to clone %s. %w", gitURL.GetRepoName(), err)
}
return tmpDir, nil
}

View File

@@ -12,7 +12,7 @@ func loadResourcesFromUrl(inputPatterns []string) (map[string][]workloadinterfac
if len(inputPatterns) == 0 {
return nil, nil
}
g, err := giturl.NewGitURL(inputPatterns[0])
g, err := giturl.NewGitAPI(inputPatterns[0])
if err != nil {
return nil, nil
}

View File

@@ -17,6 +17,7 @@ const (
JunitResultFormat string = "junit"
PrometheusFormat string = "prometheus"
PdfFormat string = "pdf"
HtmlFormat string = "html"
)
type IPrinter interface {

View File

@@ -0,0 +1,154 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>Kubescape Scan Report</title>
</head>
<style>
:root {
--cell-padding-vertical: 0.25em;
--cell-padding-horizontal: 0.25em;
--font-family-sans: system-ui, -apple-system, sans-serif;
}
body {
max-width: 60em;
margin: auto;
font-family: var(--font-family-sans);
}
table {
width: 100%;
border-top: 0.1em solid black;
border-bottom: 0.1em solid black;
border-collapse: collapse;
table-layout: fixed;
}
th {
text-align: left;
}
td, th {
padding-top: var(--cell-padding-vertical);
padding-bottom: var(--cell-padding-vertical);
padding-right: var(--cell-padding-horizontal);
vertical-align: top;
}
td > p {
margin: 0;
word-break: break-all;
hyphens: auto;
}
thead {
border-bottom: 0.01em solid black;
}
.numericCell {
text-align: right;
}
.controlSeverityCell {
width: 10%;
}
.controlNameCell {
width: 50%;
}
.controlRiskCell {
width: 10%;
}
.resourceSeverityCell {
width: 10%;
}
.resourceNameCell {
width: 30%;
}
.resourceURLCell {
width: 10%;
}
.resourceRemediationCell {
width: 50%;
}
.logo {
width: 25%;
float: right;
}
</style>
<body>
<img class="logo" src="https://raw.githubusercontent.com/armosec/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>
<table>
<thead>
<tr>
<th>All</th>
<th>Failed</th>
<th>Excluded</th>
<th>Skipped</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ .NumberOfControls.All }}</td>
<td>{{ .NumberOfControls.Failed }}</td>
<td>{{ .NumberOfControls.Excluded }}</td>
<td>{{ .NumberOfControls.Skipped }}</td>
</tr>
</tbody>
</table>
<h3>Details</h3>
<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>
</thead>
<tbody>
{{ $sorted := sortBySeverityName .Controls }}
{{ range $control := $sorted }}
<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">{{ float32ToInt $control.Score }}</td>
</tr>
</tr>
{{ end }}
<tbody>
</table>
{{ end }}
<h2>By Resource</h2>
{{ $sortedResourceTableView := sortByNamespace .ResourceTableView }}
{{ range $sortedResourceTableView }}
<h3>Name: {{ .Resource.GetName }}</h3>
<p>ApiVersion: {{ .Resource.GetApiVersion }}</p>
<p>Kind: {{ .Resource.GetKind }}</p>
<p>Name: {{ .Resource.GetName }}</p>
<p>Namespace: {{ .Resource.GetNamespace }}</p>
<table>
<thead>
<tr>
<th class="resourceSeverityCell">Severity</th>
<th class="resourceNameCell">Name</th>
<th class="resourceURLCell">Docs</th>
<th class="resourceRemediationCell">Assistant Remediation</th>
</tr>
</thead>
<tbody>
{{ range .ControlsResult }}
<tr>
<td class="resourceSeverityCell">{{ .Severity }}</td>
<td class="resourceNameCell">{{ .Name }}</td>
<td class="resourceURLCell"><a href="https://hub.armo.cloud/docs/{{ lower .URL }}">{{ .URL }}</a></td>
<td class="resourceRemediationCell">{{ range .FailedPaths }} <p>{{ . }}</p> {{ end }}</td>
</tr>
{{ end }}
</tbody>
</table>
</div>
{{ end }}
</body>
</html>

View File

@@ -0,0 +1,151 @@
package v2
import (
_ "embed"
"html/template"
"os"
"path/filepath"
"sort"
"strings"
"github.com/armosec/kubescape/v2/core/cautils"
"github.com/armosec/kubescape/v2/core/cautils/logger"
"github.com/armosec/kubescape/v2/core/cautils/logger/helpers"
"github.com/armosec/kubescape/v2/core/pkg/resultshandling/printer"
"github.com/armosec/opa-utils/reporthandling/apis"
"github.com/armosec/opa-utils/reporthandling/results/v1/reportsummary"
"github.com/armosec/opa-utils/reporthandling/results/v1/resourcesresults"
)
const (
htmlOutputFile = "report"
htmlOutputExt = ".html"
)
//go:embed html/report.gohtml
var reportTemplate string
type HTMLReportingCtx struct {
OPASessionObj *cautils.OPASessionObj
ResourceTableView ResourceTableView
}
type HtmlPrinter struct {
writer *os.File
}
func NewHtmlPrinter() *HtmlPrinter {
return &HtmlPrinter{}
}
func (htmlPrinter *HtmlPrinter) SetWriter(outputFile string) {
if outputFile == "" {
outputFile = htmlOutputFile
}
if filepath.Ext(strings.TrimSpace(outputFile)) != htmlOutputExt {
outputFile = outputFile + htmlOutputExt
}
htmlPrinter.writer = printer.GetWriter(outputFile)
}
func (htmlPrinter *HtmlPrinter) ActionPrint(opaSessionObj *cautils.OPASessionObj) {
tplFuncMap := template.FuncMap{
"sum": func(nums ...int) int {
total := 0
for _, n := range nums {
total += n
}
return total
},
"float32ToInt": cautils.Float32ToInt,
"lower": strings.ToLower,
"sortByNamespace": func(resourceTableView ResourceTableView) ResourceTableView {
sortedResourceTableView := make(ResourceTableView, len(resourceTableView))
copy(sortedResourceTableView, resourceTableView)
sort.SliceStable(
sortedResourceTableView,
func(i, j int) bool {
return sortedResourceTableView[i].Resource.GetNamespace() < sortedResourceTableView[j].Resource.GetNamespace()
},
)
return sortedResourceTableView
},
"controlSeverityToString": apis.ControlSeverityToString,
"sortBySeverityName": func(controlSummaries map[string]reportsummary.ControlSummary) []reportsummary.ControlSummary {
sortedSlice := make([]reportsummary.ControlSummary, 0, len(controlSummaries))
for _, val := range controlSummaries {
sortedSlice = append(sortedSlice, val)
}
sort.SliceStable(
sortedSlice,
func(i, j int) bool {
//First sort by Severity descending
iSeverity := apis.ControlSeverityToInt(sortedSlice[i].GetScoreFactor())
jSeverity := apis.ControlSeverityToInt(sortedSlice[j].GetScoreFactor())
if iSeverity > jSeverity {
return true
}
if iSeverity < jSeverity {
return false
}
//And then by Name ascending
return sortedSlice[i].GetName() < sortedSlice[j].GetName()
},
)
return sortedSlice
},
}
tpl := template.Must(
template.New("htmlReport").Funcs(tplFuncMap).Parse(reportTemplate),
)
resourceTableView := bulidResourceTableView(opaSessionObj)
reportingCtx := HTMLReportingCtx{opaSessionObj, resourceTableView}
err := tpl.Execute(htmlPrinter.writer, reportingCtx)
if err != nil {
logger.L().Error("failed to render template", helpers.Error(err))
}
}
func (htmlPrinter *HtmlPrinter) Score(score float32) {
return
}
func bulidResourceTableView(opaSessionObj *cautils.OPASessionObj) ResourceTableView {
resourceTableView := make(ResourceTableView, 0)
for resourceID, result := range opaSessionObj.ResourcesResult {
if result.GetStatus(nil).IsFailed() {
resource := opaSessionObj.AllResources[resourceID]
ctlResults := buildResourceControlResultTable(result.AssociatedControls, &opaSessionObj.Report.SummaryDetails)
resourceTableView = append(resourceTableView, ResourceResult{resource, ctlResults})
}
}
return resourceTableView
}
func buildResourceControlResult(resourceControl resourcesresults.ResourceAssociatedControl, control reportsummary.IControlSummary) ResourceControlResult {
ctlSeverity := apis.ControlSeverityToString(control.GetScoreFactor())
ctlName := resourceControl.GetName()
ctlURL := resourceControl.GetID()
failedPaths := failedPathsToString(&resourceControl)
return ResourceControlResult{ctlSeverity, ctlName, ctlURL, failedPaths}
}
func buildResourceControlResultTable(resourceControls []resourcesresults.ResourceAssociatedControl, summaryDetails *reportsummary.SummaryDetails) []ResourceControlResult {
var ctlResults []ResourceControlResult
for _, resourceControl := range resourceControls {
if resourceControl.GetStatus(nil).IsFailed() {
control := summaryDetails.Controls.GetControl(reportsummary.EControlCriteriaName, resourceControl.GetName())
ctlResult := buildResourceControlResult(resourceControl, control)
ctlResults = append(ctlResults, ctlResult)
}
}
return ctlResults
}

View File

@@ -33,7 +33,7 @@ func NewPrettyPrinter(verboseMode bool, formatVersion string, viewType cautils.V
}
func (prettyPrinter *PrettyPrinter) ActionPrint(opaSessionObj *cautils.OPASessionObj) {
fmt.Fprintf(prettyPrinter.writer, "\n"+getSperator("^")+"\n")
fmt.Fprintf(prettyPrinter.writer, "\n"+getSeparator("^")+"\n")
sortedControlNames := getSortedControlsNames(opaSessionObj.Report.SummaryDetails.Controls) // ListControls().All())
@@ -253,7 +253,7 @@ func controlCountersForSummary(counters reportsummary.ICounters) string {
func controlCountersForResource(l *helpersv1.AllLists) string {
return fmt.Sprintf("Controls: %d (Failed: %d, Excluded: %d)", len(l.All()), len(l.Failed()), len(l.Excluded()))
}
func getSperator(sep string) string {
func getSeparator(sep string) string {
s := ""
for i := 0; i < 80; i++ {
s += sep

View File

@@ -0,0 +1,19 @@
package v2
import (
"github.com/armosec/k8s-interface/workloadinterface"
)
type ResourceTableView []ResourceResult
type ResourceResult struct {
Resource workloadinterface.IMetadata
ControlsResult []ResourceControlResult
}
type ResourceControlResult struct {
Severity string
Name string
URL string
FailedPaths []string
}

View File

@@ -29,10 +29,10 @@ func (prettyPrinter *PrettyPrinter) resourceTable(opaSessionObj *cautils.OPASess
if !ok {
continue
}
fmt.Fprintf(prettyPrinter.writer, "\n"+getSperator("#")+"\n\n")
fmt.Fprintf(prettyPrinter.writer, fmt.Sprintf("\n%s\n\n", getSeparator("#")))
if source, ok := opaSessionObj.ResourceSource[resourceID]; ok {
fmt.Fprintf(prettyPrinter.writer, "Source: %s\n", source)
fmt.Fprintf(prettyPrinter.writer, "Source: %s\n", source.RelativePath)
}
fmt.Fprintf(prettyPrinter.writer, "ApiVersion: %s\n", resource.GetApiVersion())
fmt.Fprintf(prettyPrinter.writer, "Kind: %s\n", resource.GetKind())

View File

@@ -62,13 +62,13 @@ func mapInfoToPrintInfo(controls reportsummary.ControlSummaries) []infoStars {
return infoToPrintInfo
}
func finalizeResources(results []resourcesresults.Result, allResources map[string]workloadinterface.IMetadata, resourcesSource map[string]string) []reporthandling.Resource {
func finalizeResources(results []resourcesresults.Result, allResources map[string]workloadinterface.IMetadata, resourcesSource map[string]reporthandling.Source) []reporthandling.Resource {
resources := make([]reporthandling.Resource, 0)
for i := range results {
if obj, ok := allResources[results[i].ResourceID]; ok {
resource := *reporthandling.NewResourceIMetadata(obj)
if r, ok := resourcesSource[results[i].ResourceID]; ok {
resource.SetSource(&reporthandling.Source{Path: r})
resource.SetSource(&r)
}
resources = append(resources, resource)
}

View File

@@ -93,7 +93,11 @@ func (report *ReportEventReceiver) GetURL() string {
q := u.Query()
if report.customerAdminEMail != "" || report.token == "" { // data has been submitted
u.Path = fmt.Sprintf("configuration-scanning/%s", report.clusterName)
if report.clusterName != "" {
u.Path = fmt.Sprintf("configuration-scanning/%s", report.clusterName)
} else {
u.Path = fmt.Sprintf("repositories-scan/%s", report.reportID)
}
} else {
u.Path = "account/sign-up"
q.Add("invitationToken", report.token)
@@ -151,11 +155,11 @@ func (report *ReportEventReceiver) setResults(reportObj *reporthandlingv2.Postur
return nil
}
func (report *ReportEventReceiver) setResources(reportObj *reporthandlingv2.PostureReport, allResources map[string]workloadinterface.IMetadata, resourcesSource map[string]string, counter, reportCounter *int, host string) error {
func (report *ReportEventReceiver) setResources(reportObj *reporthandlingv2.PostureReport, allResources map[string]workloadinterface.IMetadata, resourcesSource map[string]reporthandling.Source, counter, reportCounter *int, host string) error {
for resourceID, v := range allResources {
resource := reporthandling.NewResourceIMetadata(v)
if r, ok := resourcesSource[resourceID]; ok {
resource.SetSource(&reporthandling.Source{Path: r})
resource.SetSource(&r)
}
r, err := json.Marshal(resource)
if err != nil {

View File

@@ -16,7 +16,8 @@ func (report *ReportEventReceiver) initEventReceiverURL() {
urlObj.Path = "/k8s/v2/postureReport"
q := urlObj.Query()
q.Add("customerGUID", uuid.MustParse(report.customerGUID).String())
q.Add("clusterName", report.clusterName)
q.Add("contextName", report.clusterName)
q.Add("clusterName", report.clusterName) // deprecated
urlObj.RawQuery = q.Encode()

View File

@@ -95,6 +95,8 @@ func NewPrinter(printFormat, formatVersion string, verboseMode bool, viewType ca
return printerv2.NewPrometheusPrinter(verboseMode)
case printer.PdfFormat:
return printerv2.NewPdfPrinter()
case printer.HtmlFormat:
return printerv2.NewHtmlPrinter()
default:
return printerv2.NewPrettyPrinter(verboseMode, formatVersion, viewType)
}

143
go.mod
View File

@@ -1,44 +1,45 @@
module github.com/armosec/kubescape/v2
go 1.17
go 1.18
require (
github.com/armosec/armoapi-go v0.0.73
github.com/armosec/go-git-url v0.0.4
github.com/armosec/k8s-interface v0.0.76
github.com/armosec/opa-utils v0.0.140
github.com/armosec/armoapi-go v0.0.95
github.com/armosec/go-git-url v0.0.13
github.com/armosec/k8s-interface v0.0.78
github.com/armosec/opa-utils v0.0.152
github.com/armosec/rbac-utils v0.0.14
github.com/armosec/utils-go v0.0.5
github.com/armosec/utils-k8s-go v0.0.6
github.com/armosec/utils-k8s-go v0.0.7
github.com/briandowns/spinner v1.18.1
github.com/enescakir/emoji v1.0.0
github.com/fatih/color v1.13.0
github.com/francoispqt/gojay v1.2.13
github.com/go-git/go-git/v5 v5.4.2
github.com/google/uuid v1.3.0
github.com/johnfercher/maroto v0.36.1
github.com/johnfercher/maroto v0.37.0
github.com/mattn/go-isatty v0.0.14
github.com/olekukonko/tablewriter v0.0.5
github.com/open-policy-agent/opa v0.39.0
github.com/open-policy-agent/opa v0.41.0
github.com/spf13/cobra v1.4.0
github.com/stretchr/testify v1.7.1
github.com/whilp/git-urls v1.0.0
go.uber.org/zap v1.21.0
golang.org/x/mod v0.5.1
gopkg.in/yaml.v2 v2.4.0
k8s.io/api v0.23.5
k8s.io/apimachinery v0.23.5
k8s.io/client-go v0.23.5
k8s.io/api v0.24.2
k8s.io/apimachinery v0.24.2
k8s.io/client-go v0.24.2
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9
sigs.k8s.io/yaml v1.3.0
)
require (
cloud.google.com/go v0.99.0 // indirect
cloud.google.com/go/container v1.0.0 // indirect
github.com/Azure/azure-sdk-for-go v63.0.0+incompatible // indirect
cloud.google.com/go/compute v1.7.0 // indirect
cloud.google.com/go/container v1.2.0 // indirect
github.com/Azure/azure-sdk-for-go v65.0.0+incompatible // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.24 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.18 // indirect
github.com/Azure/go-autorest/autorest v0.11.27 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.20 // indirect
github.com/Azure/go-autorest/autorest/azure/auth v0.5.11 // indirect
github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 // indirect
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
@@ -46,89 +47,105 @@ require (
github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/Microsoft/go-winio v0.5.2 // indirect
github.com/OneOfOne/xxhash v1.2.8 // indirect
github.com/aws/aws-sdk-go v1.41.11 // indirect
github.com/aws/aws-sdk-go-v2 v1.12.0 // indirect
github.com/aws/aws-sdk-go-v2/config v1.12.0 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.7.0 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.9.0 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.3 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.1.0 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.3 // indirect
github.com/aws/aws-sdk-go-v2/service/eks v1.17.0 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.6.0 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.8.0 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.13.0 // indirect
github.com/aws/smithy-go v1.9.1 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20220517143526-88bb52951d5b // indirect
github.com/acomagu/bufpipe v1.0.3 // indirect
github.com/agnivade/levenshtein v1.1.1 // indirect
github.com/aws/aws-sdk-go v1.44.36 // indirect
github.com/aws/aws-sdk-go-v2 v1.16.5 // indirect
github.com/aws/aws-sdk-go-v2/config v1.15.11 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.12.6 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.6 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.12 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.6 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.13 // indirect
github.com/aws/aws-sdk-go-v2/service/eks v1.21.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.6 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.11.9 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.16.7 // indirect
github.com/aws/smithy-go v1.11.3 // indirect
github.com/boombuler/barcode v1.0.1 // indirect
github.com/census-instrumentation/opencensus-proto v0.3.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 // indirect
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490 // indirect
github.com/coreos/go-oidc v2.2.1+incompatible // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/docker/docker v20.10.9+incompatible // indirect
github.com/docker/docker v20.10.17+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/envoyproxy/go-control-plane v0.10.1 // indirect
github.com/envoyproxy/protoc-gen-validate v0.6.2 // indirect
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-git/gcfg v1.5.0 // indirect
github.com/go-git/go-billy/v5 v5.3.1 // indirect
github.com/go-gota/gota v0.12.0 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.20.0 // indirect
github.com/go-openapi/swag v0.21.1 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.2.0 // indirect
github.com/golang-jwt/jwt/v4 v4.4.1 // indirect
github.com/golang/glog v1.0.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.7 // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/googleapis/gax-go/v2 v2.1.1 // indirect
github.com/googleapis/gnostic v0.5.5 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/google/gnostic v0.6.9 // indirect
github.com/google/go-cmp v0.5.8 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.1.0 // indirect
github.com/googleapis/gax-go/v2 v2.4.0 // indirect
github.com/imdario/mergo v0.3.13 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/jung-kurt/gofpdf v1.16.2 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/pquerna/cachecontrol v0.1.0 // indirect
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect
github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245 // indirect
github.com/sergi/go-diff v1.2.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/vektah/gqlparser/v2 v2.4.5 // indirect
github.com/xanzy/ssh-agent v0.3.1 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/yashtewari/glob-intersection v0.1.0 // indirect
go.opencensus.io v0.23.0 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
golang.org/x/net v0.0.0-20211209124913-491a49abca63 // indirect
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.8.0 // indirect
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
golang.org/x/net v0.0.0-20220615171555-694bf12d69de // indirect
golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb // indirect
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c // indirect
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
gonum.org/v1/gonum v0.9.1 // indirect
google.golang.org/api v0.62.0 // indirect
golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect
gonum.org/v1/gonum v0.11.0 // indirect
google.golang.org/api v0.84.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa // indirect
google.golang.org/grpc v1.45.0 // indirect
google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad // indirect
google.golang.org/grpc v1.47.0 // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
k8s.io/klog/v2 v2.30.0 // indirect
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 // indirect
sigs.k8s.io/controller-runtime v0.11.1 // indirect
sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/klog/v2 v2.60.1 // indirect
k8s.io/kube-openapi v0.0.0-20220614142933-1062c7ade5f8 // indirect
sigs.k8s.io/controller-runtime v0.12.1 // indirect
sigs.k8s.io/json v0.0.0-20220525155127-227cbc7cc124 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
)

1071
go.sum

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,542 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "grafana",
"uid": "-- Grafana --"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"target": {
"limit": 100,
"matchAny": false,
"tags": [],
"type": "dashboard"
},
"type": "dashboard"
}
]
},
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"id": 27,
"links": [],
"liveNow": false,
"panels": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 13,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 2,
"pointSize": 4,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 24,
"x": 0,
"y": 0
},
"id": 2,
"options": {
"legend": {
"calcs": [],
"displayMode": "hidden",
"placement": "bottom"
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"expr": "kubescape_cluster_riskScore",
"refId": "A"
}
],
"title": "Overtime Cluster Risk score",
"transparent": true,
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "points",
"fillOpacity": 10,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 4,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": true,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "short"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 8
},
"id": 7,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom"
},
"tooltip": {
"mode": "multi",
"sort": "none"
}
},
"pluginVersion": "8.5.0",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"exemplar": false,
"expr": "sum (kubescape_control_riskScore) by (name)",
"instant": false,
"interval": "",
"legendFormat": "{{link}}",
"range": true,
"refId": "A"
}
],
"title": "Overtime Controls Risk score ",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": [
{
"__systemRef": "hideSeriesFrom",
"matcher": {
"id": "byNames",
"options": {
"mode": "exclude",
"names": [
"{__name__=\"kubescape_framework_riskScore\", container=\"kubescape\", endpoint=\"http\", instance=\"172.17.0.9:8080\", job=\"armo-kubescape\", name=\"DevOpsBest\", namespace=\"armo-system\", pod=\"armo-kubescape-66555d4db6-wznwg\", service=\"armo-kubescape\"}"
],
"prefix": "All except:",
"readOnly": true
}
},
"properties": [
{
"id": "custom.hideFrom",
"value": {
"legend": false,
"tooltip": false,
"viz": false
}
}
]
}
]
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 8
},
"id": 5,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom"
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"exemplar": false,
"expr": "sum(kubescape_framework_riskScore) by (name)",
"hide": false,
"instant": true,
"legendFormat": "{{name}}",
"range": false,
"refId": "A"
}
],
"title": "Overtime Frameworks Risk score",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"description": "Number of Resources that failed/passed or excluded",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
}
},
"mappings": []
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 16
},
"id": 4,
"options": {
"displayLabels": [
"percent"
],
"legend": {
"displayMode": "list",
"placement": "right",
"values": []
},
"pieType": "pie",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"tooltip": {
"mode": "multi",
"sort": "none"
}
},
"pluginVersion": "8.5.0",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "sum(kubescape_control_count_resources_passed)",
"hide": false,
"legendFormat": "passed",
"range": true,
"refId": "C"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"exemplar": false,
"expr": "sum(kubescape_control_count_resources_failed)",
"hide": false,
"instant": true,
"legendFormat": "failed",
"range": false,
"refId": "A"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"exemplar": false,
"expr": "sum(kubescape_control_count_resources_exclude)",
"hide": false,
"instant": false,
"legendFormat": "exclude",
"range": true,
"refId": "B"
}
],
"title": "Resources by Status",
"type": "piechart"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"description": "Number of controls that failed/passed or excluded\n",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
}
},
"mappings": []
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 16
},
"id": 8,
"options": {
"displayLabels": [
"percent"
],
"legend": {
"displayMode": "list",
"placement": "right",
"values": []
},
"pieType": "pie",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "8.5.0",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"exemplar": false,
"expr": "kubescape_cluster_count_control_failed",
"hide": false,
"instant": true,
"legendFormat": "failed",
"range": false,
"refId": "A"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"exemplar": false,
"expr": "kubescape_cluster_count_control_exclude",
"hide": false,
"instant": false,
"legendFormat": "exclude",
"range": true,
"refId": "B"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"exemplar": false,
"expr": "kubescape_cluster_count_control_passed",
"hide": false,
"instant": false,
"legendFormat": "passed",
"range": true,
"refId": "C"
}
],
"title": "Controls by Status",
"type": "piechart"
}
],
"schemaVersion": 36,
"style": "dark",
"tags": [],
"templating": {
"list": []
},
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "Kubescape",
"uid": "SwdcJornz",
"version": 7,
"weekStart": ""
}

View File

@@ -1,12 +1,12 @@
module github.com/armosec/kubescape/v2/httphandler
go 1.17
go 1.18
replace github.com/armosec/kubescape/v2 => ../
require (
github.com/armosec/kubescape/v2 v2.0.0-00010101000000-000000000000
github.com/armosec/opa-utils v0.0.140
github.com/armosec/opa-utils v0.0.152
github.com/armosec/utils-go v0.0.5
github.com/google/uuid v1.3.0
github.com/gorilla/mux v1.8.0
@@ -16,12 +16,12 @@ require (
)
require (
cloud.google.com/go v0.99.0 // indirect
cloud.google.com/go/container v1.0.0 // indirect
github.com/Azure/azure-sdk-for-go v63.0.0+incompatible // indirect
cloud.google.com/go/compute v1.7.0 // indirect
cloud.google.com/go/container v1.2.0 // indirect
github.com/Azure/azure-sdk-for-go v65.0.0+incompatible // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.24 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.18 // indirect
github.com/Azure/go-autorest/autorest v0.11.27 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.20 // indirect
github.com/Azure/go-autorest/autorest/azure/auth v0.5.11 // indirect
github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 // indirect
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
@@ -29,109 +29,126 @@ require (
github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/Microsoft/go-winio v0.5.2 // indirect
github.com/OneOfOne/xxhash v1.2.8 // indirect
github.com/armosec/armoapi-go v0.0.73 // indirect
github.com/armosec/go-git-url v0.0.4 // indirect
github.com/armosec/k8s-interface v0.0.76 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20220517143526-88bb52951d5b // indirect
github.com/acomagu/bufpipe v1.0.3 // indirect
github.com/agnivade/levenshtein v1.1.1 // indirect
github.com/armosec/armoapi-go v0.0.95 // indirect
github.com/armosec/go-git-url v0.0.13 // indirect
github.com/armosec/k8s-interface v0.0.78 // indirect
github.com/armosec/rbac-utils v0.0.14 // indirect
github.com/armosec/utils-k8s-go v0.0.6 // indirect
github.com/aws/aws-sdk-go v1.41.11 // indirect
github.com/aws/aws-sdk-go-v2 v1.12.0 // indirect
github.com/aws/aws-sdk-go-v2/config v1.12.0 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.7.0 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.9.0 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.3 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.1.0 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.3 // indirect
github.com/aws/aws-sdk-go-v2/service/eks v1.17.0 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.6.0 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.8.0 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.13.0 // indirect
github.com/aws/smithy-go v1.9.1 // indirect
github.com/armosec/utils-k8s-go v0.0.7 // indirect
github.com/aws/aws-sdk-go v1.44.36 // indirect
github.com/aws/aws-sdk-go-v2 v1.16.5 // indirect
github.com/aws/aws-sdk-go-v2/config v1.15.11 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.12.6 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.6 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.12 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.6 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.13 // indirect
github.com/aws/aws-sdk-go-v2/service/eks v1.21.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.6 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.11.9 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.16.7 // indirect
github.com/aws/smithy-go v1.11.3 // indirect
github.com/boombuler/barcode v1.0.1 // indirect
github.com/briandowns/spinner v1.18.1 // indirect
github.com/census-instrumentation/opencensus-proto v0.3.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 // indirect
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490 // indirect
github.com/coreos/go-oidc v2.2.1+incompatible // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/docker/docker v20.10.9+incompatible // indirect
github.com/docker/docker v20.10.17+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/enescakir/emoji v1.0.0 // indirect
github.com/envoyproxy/go-control-plane v0.10.1 // indirect
github.com/envoyproxy/protoc-gen-validate v0.6.2 // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-git/gcfg v1.5.0 // indirect
github.com/go-git/go-billy/v5 v5.3.1 // indirect
github.com/go-git/go-git/v5 v5.4.2 // indirect
github.com/go-gota/gota v0.12.0 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.20.0 // indirect
github.com/go-openapi/swag v0.21.1 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.2.0 // indirect
github.com/golang-jwt/jwt/v4 v4.4.1 // indirect
github.com/golang/glog v1.0.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.7 // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/googleapis/gax-go/v2 v2.1.1 // indirect
github.com/googleapis/gnostic v0.5.5 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/google/gnostic v0.6.9 // indirect
github.com/google/go-cmp v0.5.8 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.1.0 // indirect
github.com/googleapis/gax-go/v2 v2.4.0 // indirect
github.com/imdario/mergo v0.3.13 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/johnfercher/maroto v0.36.1 // indirect
github.com/johnfercher/maroto v0.37.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/jung-kurt/gofpdf v1.16.2 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/open-policy-agent/opa v0.39.0 // indirect
github.com/open-policy-agent/opa v0.41.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/pquerna/cachecontrol v0.1.0 // indirect
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect
github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245 // indirect
github.com/sergi/go-diff v1.2.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/vektah/gqlparser/v2 v2.4.5 // indirect
github.com/whilp/git-urls v1.0.0 // indirect
github.com/xanzy/ssh-agent v0.3.1 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/yashtewari/glob-intersection v0.1.0 // indirect
go.opencensus.io v0.23.0 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.21.0 // indirect
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
golang.org/x/mod v0.5.1 // indirect
golang.org/x/net v0.0.0-20211209124913-491a49abca63 // indirect
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect
golang.org/x/net v0.0.0-20220615171555-694bf12d69de // indirect
golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb // indirect
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c // indirect
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
gonum.org/v1/gonum v0.9.1 // indirect
google.golang.org/api v0.62.0 // indirect
golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect
gonum.org/v1/gonum v0.11.0 // indirect
google.golang.org/api v0.84.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa // indirect
google.golang.org/grpc v1.45.0 // indirect
google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad // indirect
google.golang.org/grpc v1.47.0 // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
k8s.io/api v0.23.5 // indirect
k8s.io/apimachinery v0.23.5 // indirect
k8s.io/client-go v0.23.5 // indirect
k8s.io/klog/v2 v2.30.0 // indirect
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 // indirect
sigs.k8s.io/controller-runtime v0.11.1 // indirect
sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.24.2 // indirect
k8s.io/apimachinery v0.24.2 // indirect
k8s.io/client-go v0.24.2 // indirect
k8s.io/klog/v2 v2.60.1 // indirect
k8s.io/kube-openapi v0.0.0-20220614142933-1062c7ade5f8 // indirect
sigs.k8s.io/controller-runtime v0.12.1 // indirect
sigs.k8s.io/json v0.0.0-20220525155127-227cbc7cc124 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,20 @@
#!/bin/bash
set -e
while getopts v: option
do
case ${option} in
v) RELEASE="download/${OPTARG}";;
esac
done
if [ -z ${RELEASE} ]; then
RELEASE="latest/download"
fi
echo -e "\033[0;36mInstalling Kubescape..."
echo
BASE_DIR=~/.kubescape
KUBESCAPE_EXEC=kubescape
KUBESCAPE_ZIP=kubescape.zip
@@ -20,7 +31,8 @@ fi
mkdir -p $BASE_DIR
OUTPUT=$BASE_DIR/$KUBESCAPE_EXEC
DOWNLOAD_URL="https://github.com/armosec/kubescape/releases/latest/download/kubescape-${osName}-latest"
DOWNLOAD_URL="https://github.com/armosec/kubescape/releases/${RELEASE}/kubescape-${osName}-latest"
curl --progress-bar -L $DOWNLOAD_URL -o $OUTPUT
# Checking if SUDO needed/exists