Compare commits

...

8 Commits

Author SHA1 Message Date
dwertent
6099f46dea adding docker build 2022-03-14 18:34:34 +02:00
dwertent
f7c0c95d3b adding tests to build 2022-03-13 19:05:06 +02:00
dwertent
b8df07b547 fixed unitest 2022-03-13 18:59:39 +02:00
dwertent
d0e2730518 add cautils to core 2022-03-13 18:14:48 +02:00
dwertent
6dab82f01a fixed output format 2022-03-13 15:03:22 +02:00
dwertent
7a01116db5 adding ks interface 2022-03-13 10:59:38 +02:00
dwertent
8f1e4ceff0 split pkg 2022-03-13 09:59:57 +02:00
dwertent
66196c0d56 pass info in call 2022-03-10 17:13:51 +02:00
177 changed files with 4544 additions and 829 deletions

View File

@@ -33,9 +33,15 @@ jobs:
uses: actions/setup-go@v2
with:
go-version: 1.17
- name: Test cmd pkg
run: cd cmd && go test -v ./...
- name: Test core pkg
run: cd core && go test -v ./...
- name: Test
run: go test -v ./...
- name: Test httphandler pkg
run: cd httphandler && go test -v ./...
- name: Build
env:
@@ -45,7 +51,7 @@ jobs:
ArmoERServer: report.armo.cloud
ArmoWebsite: portal.armo.cloud
CGO_ENABLED: 0
run: python3 --version && python3 build.py
run: cd cmd && python3 --version && python3 build.py
- name: Smoke Testing
env:

View File

@@ -18,8 +18,14 @@ jobs:
with:
go-version: 1.17
- name: Test
run: go test -v ./...
- name: Test cmd pkg
run: cd cmd && go test -v ./...
- name: Test core pkg
run: cd core && go test -v ./...
- name: Test httphandler pkg
run: cd httphandler && go test -v ./...
- name: Build
env:
@@ -29,7 +35,7 @@ jobs:
ArmoERServer: report.armo.cloud
ArmoWebsite: portal.armo.cloud
CGO_ENABLED: 0
run: python3 --version && python3 build.py
run: cd cmd && python3 --version && python3 build.py
- name: Smoke Testing
env:

View File

@@ -19,8 +19,14 @@ jobs:
with:
go-version: 1.17
- name: Test
run: go test -v ./...
- name: Test cmd pkg
run: cd cmd && go test -v ./...
- name: Test core pkg
run: cd core && go test -v ./...
- name: Test httphandler pkg
run: cd httphandler && go test -v ./...
- name: Build
env:
@@ -30,7 +36,7 @@ jobs:
ArmoERServer: report.armo.cloud
ArmoWebsite: portal.armo.cloud
CGO_ENABLED: 0
run: python3 --version && python3 build.py
run: cd cmd && python3 --version && python3 build.py
- name: Smoke Testing
env:

View File

@@ -17,13 +17,14 @@ RUN pip3 install --no-cache --upgrade pip setuptools
WORKDIR /work
ADD . .
WORKDIR /work/httphandler
RUN python build.py
RUN ls -ltr build/ubuntu-latest
FROM alpine
COPY --from=builder /work/build/ubuntu-latest/kubescape /usr/bin/kubescape
COPY --from=builder /work/httphandler/build/ubuntu-latest/kubescape /usr/bin/kubescape
# # Download the frameworks. Use the "--use-default" flag when running kubescape
# RUN kubescape download framework nsa && kubescape download framework mitre

View File

@@ -1,7 +0,0 @@
package clihandler
func CliDelete() error {
tenant := getTenantConfig("", "", getKubernetesApi()) // change k8sinterface
return tenant.DeleteCachedConfig()
}

View File

@@ -1,7 +0,0 @@
package cliobjects
type SetConfig struct {
Account string
ClientID string
SecretKey string
}

View File

@@ -1,22 +0,0 @@
package clihandler
import (
"github.com/armosec/kubescape/clihandler/cliobjects"
)
func CliSetConfig(setConfig *cliobjects.SetConfig) error {
tenant := getTenantConfig("", "", getKubernetesApi())
if setConfig.Account != "" {
tenant.GetConfigObj().AccountID = setConfig.Account
}
if setConfig.SecretKey != "" {
tenant.GetConfigObj().SecretKey = setConfig.SecretKey
}
if setConfig.ClientID != "" {
tenant.GetConfigObj().ClientID = setConfig.ClientID
}
return tenant.UpdateCachedConfig()
}

View File

@@ -1,12 +0,0 @@
package clihandler
import (
"fmt"
"os"
)
func CliView() error {
tenant := getTenantConfig("", "", getKubernetesApi()) // change k8sinterface
fmt.Fprintf(os.Stderr, "%s\n", tenant.GetConfigObj().Config())
return nil
}

View File

@@ -1,20 +0,0 @@
package config
import (
"github.com/armosec/kubescape/cautils/logger"
"github.com/armosec/kubescape/clihandler"
"github.com/spf13/cobra"
)
func getDeleteCmd() *cobra.Command {
return &cobra.Command{
Use: "delete",
Short: "Delete cached configurations",
Long: ``,
Run: func(cmd *cobra.Command, args []string) {
if err := clihandler.CliDelete(); err != nil {
logger.L().Fatal(err.Error())
}
},
}
}

View File

@@ -1,22 +0,0 @@
package config
import (
"github.com/armosec/kubescape/cautils/logger"
"github.com/armosec/kubescape/clihandler"
"github.com/spf13/cobra"
)
func getViewCmd() *cobra.Command {
// configCmd represents the config command
return &cobra.Command{
Use: "view",
Short: "View cached configurations",
Long: ``,
Run: func(cmd *cobra.Command, args []string) {
if err := clihandler.CliView(); err != nil {
logger.L().Fatal(err.Error())
}
},
}
}

View File

@@ -1,156 +0,0 @@
package cmd
import (
"fmt"
"os"
"strings"
"github.com/armosec/kubescape/cautils"
"github.com/armosec/kubescape/cautils/getter"
"github.com/armosec/kubescape/cautils/logger"
"github.com/armosec/kubescape/cautils/logger/helpers"
"github.com/armosec/kubescape/clihandler/cmd/completion"
"github.com/armosec/kubescape/clihandler/cmd/config"
"github.com/armosec/kubescape/clihandler/cmd/delete"
"github.com/armosec/kubescape/clihandler/cmd/download"
"github.com/armosec/kubescape/clihandler/cmd/list"
"github.com/armosec/kubescape/clihandler/cmd/scan"
"github.com/armosec/kubescape/clihandler/cmd/submit"
"github.com/armosec/kubescape/clihandler/cmd/version"
"github.com/mattn/go-isatty"
"github.com/spf13/cobra"
)
var armoBEURLs = ""
var armoBEURLsDep = ""
var rootInfo cautils.RootInfo
const envFlagUsage = "Send report results to specific URL. Format:<ReportReceiver>,<Backend>,<Frontend>.\n\t\tExample:report.armo.cloud,api.armo.cloud,portal.armo.cloud"
var ksExamples = `
# Scan command
kubescape scan --submit
# List supported frameworks
kubescape list frameworks
# Download artifacts (air-gapped environment support)
kubescape download artifacts
# View cached configurations
kubescape config view
`
var rootCmd = &cobra.Command{
Use: "kubescape",
Version: cautils.BuildNumber,
Short: "Kubescape is a tool for testing Kubernetes security posture",
Long: `Based on NSA \ MITRE ATT&CK® and other frameworks specifications`,
Example: ksExamples,
}
func Execute() {
rootCmd.Execute()
}
func init() {
rootCmd.AddCommand(scan.GetScanCommand())
rootCmd.AddCommand(download.GeDownloadCmd())
rootCmd.AddCommand(delete.GetDeleteCmd())
rootCmd.AddCommand(list.GetListCmd())
rootCmd.AddCommand(submit.GetSubmitCmd())
rootCmd.AddCommand(completion.GetCompletionCmd())
rootCmd.AddCommand(version.GetVersionCmd())
rootCmd.AddCommand(config.GetConfigCmd())
cobra.OnInitialize(initLogger, initLoggerLevel, initEnvironment, initCacheDir)
rootCmd.PersistentFlags().StringVar(&armoBEURLsDep, "environment", "", envFlagUsage)
rootCmd.PersistentFlags().StringVar(&armoBEURLs, "env", "", envFlagUsage)
rootCmd.PersistentFlags().MarkDeprecated("environment", "use 'env' instead")
rootCmd.PersistentFlags().MarkHidden("environment")
rootCmd.PersistentFlags().MarkHidden("env")
rootCmd.PersistentFlags().StringVar(&rootInfo.LoggerName, "logger-name", "", fmt.Sprintf("Logger name. Supported: %s [$KS_LOGGER_NAME]", strings.Join(logger.ListLoggersNames(), "/")))
rootCmd.PersistentFlags().MarkHidden("logger-name")
rootCmd.PersistentFlags().StringVarP(&rootInfo.Logger, "logger", "l", helpers.InfoLevel.String(), fmt.Sprintf("Logger level. Supported: %s [$KS_LOGGER]", strings.Join(helpers.SupportedLevels(), "/")))
rootCmd.PersistentFlags().StringVar(&rootInfo.CacheDir, "cache-dir", getter.DefaultLocalStore, "Cache directory [$KS_CACHE_DIR]")
rootCmd.PersistentFlags().BoolVarP(&rootInfo.DisableColor, "disable-color", "", false, "Disable Color output for logging")
}
func initLogger() {
logger.DisableColor(rootInfo.DisableColor)
if rootInfo.LoggerName == "" {
if l := os.Getenv("KS_LOGGER_NAME"); l != "" {
rootInfo.LoggerName = l
} else {
if isatty.IsTerminal(os.Stdout.Fd()) {
rootInfo.LoggerName = "pretty"
} else {
rootInfo.LoggerName = "zap"
}
}
}
logger.InitLogger(rootInfo.LoggerName)
}
func initLoggerLevel() {
if rootInfo.Logger != helpers.InfoLevel.String() {
} else if l := os.Getenv("KS_LOGGER"); l != "" {
rootInfo.Logger = l
}
if err := logger.L().SetLevel(rootInfo.Logger); err != nil {
logger.L().Fatal(fmt.Sprintf("supported levels: %s", strings.Join(helpers.SupportedLevels(), "/")), helpers.Error(err))
}
}
func initCacheDir() {
if rootInfo.CacheDir == getter.DefaultLocalStore {
getter.DefaultLocalStore = rootInfo.CacheDir
} else if cacheDir := os.Getenv("KS_CACHE_DIR"); cacheDir != "" {
getter.DefaultLocalStore = cacheDir
} else {
return // using default cache dir location
}
logger.L().Debug("cache dir updated", helpers.String("path", getter.DefaultLocalStore))
}
func initEnvironment() {
if armoBEURLsDep != "" {
armoBEURLs = armoBEURLsDep
}
urlSlices := strings.Split(armoBEURLs, ",")
if len(urlSlices) != 1 && len(urlSlices) < 3 {
logger.L().Fatal("expected at least 3 URLs (report, api, frontend, auth)")
}
switch len(urlSlices) {
case 1:
switch urlSlices[0] {
case "dev", "development":
getter.SetARMOAPIConnector(getter.NewARMOAPIDev())
case "stage", "staging":
getter.SetARMOAPIConnector(getter.NewARMOAPIStaging())
case "":
getter.SetARMOAPIConnector(getter.NewARMOAPIProd())
default:
logger.L().Fatal("--environment flag usage: " + envFlagUsage)
}
case 2:
logger.L().Fatal("--environment flag usage: " + envFlagUsage)
case 3, 4:
var armoAUTHURL string
armoERURL := urlSlices[0] // mandatory
armoBEURL := urlSlices[1] // mandatory
armoFEURL := urlSlices[2] // mandatory
if len(urlSlices) <= 4 {
armoAUTHURL = urlSlices[3]
}
getter.SetARMOAPIConnector(getter.NewARMOAPICustomized(armoERURL, armoBEURL, armoFEURL, armoAUTHURL))
}
}

19
cmd/README.md Normal file
View File

@@ -0,0 +1,19 @@
# Kubescape CLI Package
## Commands
* [Completion](#completion): Generate autocompletion script
* [Config](#config): Handle cached configurations
* [Delete](#delete): Delete configurations in Kubescape SaaS version
* [Download](#download): Download controls-inputs,exceptions,control,framework,artifacts
* [Help](#help): Help about any command
* [List](#list): List frameworks/controls will list the supported frameworks and controls
* [Scan](#scan): Scan the current running cluster or yaml files
* [Submit](#submit): Submit an object to the Kubescape SaaS version
* [Version](#version): Get kubescape version
## Global Flags
--cache-dir string Cache directory [$KS_CACHE_DIR] (default "/home/david/.kubescape")
-l, --logger string Logger level. Supported: debug/info/success/warning/error/fatal [$KS_LOGGER] (default "info")
### Completion

View File

@@ -4,7 +4,7 @@ import hashlib
import platform
import subprocess
BASE_GETTER_CONST = "github.com/armosec/kubescape/cautils/getter"
BASE_GETTER_CONST = "github.com/armosec/kubescape/core/cautils/getter"
BE_SERVER_CONST = BASE_GETTER_CONST + ".ArmoBEURL"
ER_SERVER_CONST = BASE_GETTER_CONST + ".ArmoERURL"
WEBSITE_CONST = BASE_GETTER_CONST + ".ArmoFEURL"
@@ -18,7 +18,7 @@ def checkStatus(status, msg):
def getBuildDir():
currentPlatform = platform.system()
buildDir = "build/"
buildDir = "../build/"
if currentPlatform == "Windows": buildDir += "windows-latest"
elif currentPlatform == "Linux": buildDir += "ubuntu-latest"
@@ -42,7 +42,7 @@ def main():
# Set some variables
packageName = getPackageName()
buildUrl = "github.com/armosec/kubescape/cautils.BuildNumber"
buildUrl = "github.com/armosec/kubescape/core/cautils.BuildNumber"
releaseVersion = os.getenv("RELEASE")
ArmoBEServer = os.getenv("ArmoBEServer")
ArmoERServer = os.getenv("ArmoERServer")
@@ -70,7 +70,7 @@ def main():
ldflags += " -X {}={}".format(WEBSITE_CONST, ArmoWebsite)
if ArmoAuthServer:
ldflags += " -X {}={}".format(AUTH_SERVER_CONST, ArmoAuthServer)
build_command = ["go", "build", "-o", ks_file, "-ldflags" ,ldflags]
print("Building kubescape and saving here: {}".format(ks_file))

View File

@@ -1,6 +1,7 @@
package config
import (
"github.com/armosec/kubescape/core/meta"
"github.com/spf13/cobra"
)
@@ -27,18 +28,18 @@ var (
`
)
func GetConfigCmd() *cobra.Command {
func GetConfigCmd(ks meta.IKubescape) *cobra.Command {
// configCmd represents the config command
configCmd := &cobra.Command{
Use: "config",
Short: "handle cached configurations",
Short: "Handle cached configurations",
Example: configExample,
}
configCmd.AddCommand(getDeleteCmd())
configCmd.AddCommand(getSetCmd())
configCmd.AddCommand(getSetCmd())
configCmd.AddCommand(getDeleteCmd(ks))
configCmd.AddCommand(getSetCmd(ks))
configCmd.AddCommand(getViewCmd(ks))
return configCmd
}

21
cmd/config/delete.go Normal file
View File

@@ -0,0 +1,21 @@
package config
import (
"github.com/armosec/kubescape/core/cautils/logger"
"github.com/armosec/kubescape/core/meta"
v1 "github.com/armosec/kubescape/core/meta/datastructures/v1"
"github.com/spf13/cobra"
)
func getDeleteCmd(ks meta.IKubescape) *cobra.Command {
return &cobra.Command{
Use: "delete",
Short: "Delete cached configurations",
Long: ``,
Run: func(cmd *cobra.Command, args []string) {
if err := ks.DeleteCachedConfig(&v1.DeleteConfig{}); err != nil {
logger.L().Fatal(err.Error())
}
},
}
}

View File

@@ -4,13 +4,13 @@ import (
"fmt"
"strings"
"github.com/armosec/kubescape/cautils/logger"
"github.com/armosec/kubescape/clihandler"
"github.com/armosec/kubescape/clihandler/cliobjects"
"github.com/armosec/kubescape/core/cautils/logger"
"github.com/armosec/kubescape/core/meta"
metav1 "github.com/armosec/kubescape/core/meta/datastructures/v1"
"github.com/spf13/cobra"
)
func getSetCmd() *cobra.Command {
func getSetCmd(ks meta.IKubescape) *cobra.Command {
// configCmd represents the config command
configSetCmd := &cobra.Command{
@@ -23,7 +23,7 @@ func getSetCmd() *cobra.Command {
if err != nil {
return err
}
if err := clihandler.CliSetConfig(setConfig); err != nil {
if err := ks.SetCachedConfig(setConfig); err != nil {
logger.L().Fatal(err.Error())
}
return nil
@@ -32,13 +32,13 @@ func getSetCmd() *cobra.Command {
return configSetCmd
}
var supportConfigSet = map[string]func(*cliobjects.SetConfig, string){
"accountID": func(s *cliobjects.SetConfig, account string) { s.Account = account },
"clientID": func(s *cliobjects.SetConfig, clientID string) { s.ClientID = clientID },
"secretKey": func(s *cliobjects.SetConfig, secretKey string) { s.SecretKey = secretKey },
var supportConfigSet = map[string]func(*metav1.SetConfig, string){
"accountID": func(s *metav1.SetConfig, account string) { s.Account = account },
"clientID": func(s *metav1.SetConfig, clientID string) { s.ClientID = clientID },
"secretKey": func(s *metav1.SetConfig, secretKey string) { s.SecretKey = secretKey },
}
func stringKeysToSlice(m map[string]func(*cliobjects.SetConfig, string)) []string {
func stringKeysToSlice(m map[string]func(*metav1.SetConfig, string)) []string {
l := []string{}
for i := range m {
l = append(l, i)
@@ -46,7 +46,7 @@ func stringKeysToSlice(m map[string]func(*cliobjects.SetConfig, string)) []strin
return l
}
func parseSetArgs(args []string) (*cliobjects.SetConfig, error) {
func parseSetArgs(args []string) (*metav1.SetConfig, error) {
var key string
var value string
if len(args) == 1 {
@@ -58,7 +58,7 @@ func parseSetArgs(args []string) (*cliobjects.SetConfig, error) {
key = args[0]
value = args[1]
}
setConfig := &cliobjects.SetConfig{}
setConfig := &metav1.SetConfig{}
if setConfigFunc, ok := supportConfigSet[key]; ok {
setConfigFunc(setConfig, value)

25
cmd/config/view.go Normal file
View File

@@ -0,0 +1,25 @@
package config
import (
"os"
"github.com/armosec/kubescape/core/cautils/logger"
"github.com/armosec/kubescape/core/meta"
v1 "github.com/armosec/kubescape/core/meta/datastructures/v1"
"github.com/spf13/cobra"
)
func getViewCmd(ks meta.IKubescape) *cobra.Command {
// configCmd represents the config command
return &cobra.Command{
Use: "view",
Short: "View cached configurations",
Long: ``,
Run: func(cmd *cobra.Command, args []string) {
if err := ks.ViewCachedConfig(&v1.ViewConfig{Writer: os.Stdout}); err != nil {
logger.L().Fatal(err.Error())
}
},
}
}

View File

@@ -1,12 +1,11 @@
package delete
import (
"github.com/armosec/kubescape/clihandler/cliobjects"
"github.com/armosec/kubescape/core/meta"
v1 "github.com/armosec/kubescape/core/meta/datastructures/v1"
"github.com/spf13/cobra"
)
var deleteInfo cliobjects.Delete
var deleteExceptionsExamples = `
# Delete single exception
kubescape delete exceptions "exception name"
@@ -15,7 +14,9 @@ var deleteExceptionsExamples = `
kubescape delete exceptions "first exception;second exception;third exception"
`
func GetDeleteCmd() *cobra.Command {
func GetDeleteCmd(ks meta.IKubescape) *cobra.Command {
var deleteInfo v1.Delete
var deleteCmd = &cobra.Command{
Use: "delete <command>",
Short: "Delete configurations in Kubescape SaaS version",
@@ -25,7 +26,7 @@ func GetDeleteCmd() *cobra.Command {
}
deleteCmd.PersistentFlags().StringVarP(&deleteInfo.Account, "account", "", "", "Armo portal account ID. Default will load account ID from configMap or config file")
deleteCmd.AddCommand(getExceptionsCmd())
deleteCmd.AddCommand(getExceptionsCmd(ks, &deleteInfo))
return deleteCmd
}

View File

@@ -4,12 +4,13 @@ import (
"fmt"
"strings"
"github.com/armosec/kubescape/cautils/logger"
"github.com/armosec/kubescape/clihandler"
"github.com/armosec/kubescape/core/cautils/logger"
"github.com/armosec/kubescape/core/meta"
v1 "github.com/armosec/kubescape/core/meta/datastructures/v1"
"github.com/spf13/cobra"
)
func getExceptionsCmd() *cobra.Command {
func getExceptionsCmd(ks meta.IKubescape, deleteInfo *v1.Delete) *cobra.Command {
return &cobra.Command{
Use: "exceptions <exception name>",
Short: "Delete exceptions from Kubescape SaaS version. Run 'kubescape list exceptions' for all exceptions names",
@@ -25,7 +26,7 @@ func getExceptionsCmd() *cobra.Command {
if len(exceptionsNames) == 0 {
logger.L().Fatal("missing exceptions names")
}
if err := clihandler.DeleteExceptions(deleteInfo.Account, exceptionsNames); err != nil {
if err := ks.DeleteExceptions(&v1.DeleteExceptions{Account: deleteInfo.Account, Exceptions: exceptionsNames}); err != nil {
logger.L().Fatal(err.Error())
}
},

View File

@@ -5,14 +5,14 @@ import (
"path/filepath"
"strings"
"github.com/armosec/kubescape/cautils"
"github.com/armosec/kubescape/cautils/logger"
"github.com/armosec/kubescape/clihandler"
"github.com/armosec/kubescape/core/cautils"
"github.com/armosec/kubescape/core/cautils/logger"
"github.com/armosec/kubescape/core/core"
"github.com/armosec/kubescape/core/meta"
v1 "github.com/armosec/kubescape/core/meta/datastructures/v1"
"github.com/spf13/cobra"
)
var downloadInfo = cautils.DownloadInfo{}
var (
downloadExample = `
# Download all artifacts and save them in the default path (~/.kubescape)
@@ -39,18 +39,20 @@ var (
`
)
func GeDownloadCmd() *cobra.Command {
func GeDownloadCmd(ks meta.IKubescape) *cobra.Command {
var downloadInfo = v1.DownloadInfo{}
downloadCmd := &cobra.Command{
Use: "download <policy> <policy name>",
Short: fmt.Sprintf("Download %s", strings.Join(clihandler.DownloadSupportCommands(), ",")),
Short: fmt.Sprintf("Download %s", strings.Join(core.DownloadSupportCommands(), ",")),
Long: ``,
Example: downloadExample,
Args: func(cmd *cobra.Command, args []string) error {
supported := strings.Join(clihandler.DownloadSupportCommands(), ",")
supported := strings.Join(core.DownloadSupportCommands(), ",")
if len(args) < 1 {
return fmt.Errorf("policy type required, supported: %v", supported)
}
if cautils.StringInSlice(clihandler.DownloadSupportCommands(), args[0]) == cautils.ValueNotFound {
if cautils.StringInSlice(core.DownloadSupportCommands(), args[0]) == cautils.ValueNotFound {
return fmt.Errorf("invalid parameter '%s'. Supported parameters: %s", args[0], supported)
}
return nil
@@ -64,7 +66,7 @@ func GeDownloadCmd() *cobra.Command {
if len(args) >= 2 {
downloadInfo.Name = args[1]
}
if err := clihandler.CliDownload(&downloadInfo); err != nil {
if err := ks.Download(&downloadInfo); err != nil {
logger.L().Fatal(err.Error())
}
return nil

126
cmd/go.mod Normal file
View File

@@ -0,0 +1,126 @@
module github.com/armosec/kubescape/cmd
go 1.17
replace github.com/armosec/kubescape/core => ../core
require (
github.com/armosec/k8s-interface v0.0.68
github.com/armosec/kubescape/core v0.0.0-00010101000000-000000000000
github.com/armosec/opa-utils v0.0.116
github.com/armosec/rbac-utils v0.0.14
github.com/google/uuid v1.3.0
github.com/mattn/go-isatty v0.0.14
github.com/spf13/cobra v1.4.0
)
require (
cloud.google.com/go v0.99.0 // indirect
cloud.google.com/go/container v1.0.0 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.18 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.13 // indirect
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/OneOfOne/xxhash v1.2.8 // indirect
github.com/armosec/armoapi-go v0.0.58 // indirect
github.com/armosec/utils-go v0.0.3 // indirect
github.com/armosec/utils-k8s-go v0.0.3 // 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/boombuler/barcode v1.0.0 // 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/docker/docker v20.10.9+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.4.0 // 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/form3tech-oss/jwt-go v3.2.3+incompatible // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-gota/gota v0.12.0 // indirect
github.com/go-logr/logr v1.2.2 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/gogo/protobuf v1.3.2 // 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/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/johnfercher/maroto v0.34.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/jung-kurt/gofpdf v1.4.2 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/open-policy-agent/opa v0.38.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/pkg/errors v0.9.1 // 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/spf13/pflag v1.0.5 // 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.0.0-20180916065949-5c77d914dd0b // 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/zap v1.21.0 // indirect
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // 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/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
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa // indirect
google.golang.org/grpc v1.44.0 // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
k8s.io/api v0.23.4 // indirect
k8s.io/apimachinery v0.23.4 // indirect
k8s.io/client-go v0.23.4 // indirect
k8s.io/klog/v2 v2.30.0 // indirect
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 // indirect
k8s.io/utils v0.0.0-20211116205334-6203023598ed // indirect
sigs.k8s.io/controller-runtime v0.11.1 // indirect
sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

1482
cmd/go.sum Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -4,10 +4,11 @@ import (
"fmt"
"strings"
"github.com/armosec/kubescape/cautils"
"github.com/armosec/kubescape/cautils/logger"
"github.com/armosec/kubescape/clihandler"
"github.com/armosec/kubescape/clihandler/cliobjects"
"github.com/armosec/kubescape/core/cautils"
"github.com/armosec/kubescape/core/cautils/logger"
"github.com/armosec/kubescape/core/core"
"github.com/armosec/kubescape/core/meta"
v1 "github.com/armosec/kubescape/core/meta/datastructures/v1"
"github.com/spf13/cobra"
)
@@ -30,8 +31,8 @@ var (
`
)
func GetListCmd() *cobra.Command {
var listPolicies = cliobjects.ListPolicies{}
func GetListCmd(ks meta.IKubescape) *cobra.Command {
var listPolicies = v1.ListPolicies{}
listCmd := &cobra.Command{
Use: "list <policy> [flags]",
@@ -39,12 +40,12 @@ func GetListCmd() *cobra.Command {
Long: ``,
Example: listExample,
Args: func(cmd *cobra.Command, args []string) error {
supported := strings.Join(clihandler.ListSupportCommands(), ",")
supported := strings.Join(core.ListSupportActions(), ",")
if len(args) < 1 {
return fmt.Errorf("policy type requeued, supported: %s", supported)
}
if cautils.StringInSlice(clihandler.ListSupportCommands(), args[0]) == cautils.ValueNotFound {
if cautils.StringInSlice(core.ListSupportActions(), args[0]) == cautils.ValueNotFound {
return fmt.Errorf("invalid parameter '%s'. Supported parameters: %s", args[0], supported)
}
return nil
@@ -52,7 +53,7 @@ func GetListCmd() *cobra.Command {
RunE: func(cmd *cobra.Command, args []string) error {
listPolicies.Target = args[0]
if err := clihandler.CliList(&listPolicies); err != nil {
if err := ks.List(&listPolicies); err != nil {
logger.L().Fatal(err.Error())
}
return nil

91
cmd/root.go Normal file
View File

@@ -0,0 +1,91 @@
package main
import (
"fmt"
"strings"
"github.com/armosec/kubescape/cmd/completion"
"github.com/armosec/kubescape/cmd/config"
"github.com/armosec/kubescape/cmd/delete"
"github.com/armosec/kubescape/cmd/download"
"github.com/armosec/kubescape/cmd/list"
"github.com/armosec/kubescape/cmd/scan"
"github.com/armosec/kubescape/cmd/submit"
"github.com/armosec/kubescape/cmd/version"
"github.com/armosec/kubescape/core/cautils"
"github.com/armosec/kubescape/core/cautils/getter"
"github.com/armosec/kubescape/core/cautils/logger"
"github.com/armosec/kubescape/core/cautils/logger/helpers"
"github.com/armosec/kubescape/core/core"
"github.com/armosec/kubescape/core/meta"
"github.com/spf13/cobra"
)
var ksExamples = `
# Scan command
kubescape scan --submit
# List supported frameworks
kubescape list frameworks
# Download artifacts (air-gapped environment support)
kubescape download artifacts
# View cached configurations
kubescape config view
`
func NewDefaultKubescapeCommand() *cobra.Command {
ks := core.NewKubescape()
return getRootCmd(ks)
}
func getRootCmd(ks meta.IKubescape) *cobra.Command {
var rootInfo cautils.RootInfo
rootCmd := &cobra.Command{
Use: "kubescape",
Version: cautils.BuildNumber,
Short: "Kubescape is a tool for testing Kubernetes security posture",
Long: `Based on NSA \ MITRE ATT&CK® and other frameworks specifications`,
Example: ksExamples,
}
rootCmd.PersistentFlags().StringVar(&armoBEURLsDep, "environment", "", envFlagUsage)
rootCmd.PersistentFlags().StringVar(&armoBEURLs, "env", "", envFlagUsage)
rootCmd.PersistentFlags().MarkDeprecated("environment", "use 'env' instead")
rootCmd.PersistentFlags().MarkHidden("environment")
rootCmd.PersistentFlags().MarkHidden("env")
rootCmd.PersistentFlags().StringVar(&rootInfo.LoggerName, "logger-name", "", fmt.Sprintf("Logger name. Supported: %s [$KS_LOGGER_NAME]", strings.Join(logger.ListLoggersNames(), "/")))
rootCmd.PersistentFlags().MarkHidden("logger-name")
rootCmd.PersistentFlags().StringVarP(&rootInfo.Logger, "logger", "l", helpers.InfoLevel.String(), fmt.Sprintf("Logger level. Supported: %s [$KS_LOGGER]", strings.Join(helpers.SupportedLevels(), "/")))
rootCmd.PersistentFlags().StringVar(&rootInfo.CacheDir, "cache-dir", getter.DefaultLocalStore, "Cache directory [$KS_CACHE_DIR]")
rootCmd.PersistentFlags().BoolVarP(&rootInfo.DisableColor, "disable-color", "", false, "Disable Color output for logging")
// Initialize
initLogger(&rootInfo)
initLoggerLevel(&rootInfo)
initEnvironment(&rootInfo)
initCacheDir(&rootInfo)
// Supported commands
rootCmd.AddCommand(scan.GetScanCommand(ks))
rootCmd.AddCommand(download.GeDownloadCmd(ks))
rootCmd.AddCommand(delete.GetDeleteCmd(ks))
rootCmd.AddCommand(list.GetListCmd(ks))
rootCmd.AddCommand(submit.GetSubmitCmd(ks))
rootCmd.AddCommand(completion.GetCompletionCmd())
rootCmd.AddCommand(version.GetVersionCmd())
rootCmd.AddCommand(config.GetConfigCmd(ks))
return rootCmd
}
func main() {
ks := NewDefaultKubescapeCommand()
ks.Execute()
}

93
cmd/rootutils.go Normal file
View File

@@ -0,0 +1,93 @@
package main
import (
"fmt"
"os"
"strings"
"github.com/armosec/kubescape/core/cautils"
"github.com/armosec/kubescape/core/cautils/getter"
"github.com/armosec/kubescape/core/cautils/logger"
"github.com/armosec/kubescape/core/cautils/logger/helpers"
"github.com/mattn/go-isatty"
)
var armoBEURLs = ""
var armoBEURLsDep = ""
const envFlagUsage = "Send report results to specific URL. Format:<ReportReceiver>,<Backend>,<Frontend>.\n\t\tExample:report.armo.cloud,api.armo.cloud,portal.armo.cloud"
func initLogger(rootInfo *cautils.RootInfo) {
logger.DisableColor(rootInfo.DisableColor)
if rootInfo.LoggerName == "" {
if l := os.Getenv("KS_LOGGER_NAME"); l != "" {
rootInfo.LoggerName = l
} else {
if isatty.IsTerminal(os.Stdout.Fd()) {
rootInfo.LoggerName = "pretty"
} else {
rootInfo.LoggerName = "zap"
}
}
}
logger.InitLogger(rootInfo.LoggerName)
}
func initLoggerLevel(rootInfo *cautils.RootInfo) {
if rootInfo.Logger != helpers.InfoLevel.String() {
} else if l := os.Getenv("KS_LOGGER"); l != "" {
rootInfo.Logger = l
}
if err := logger.L().SetLevel(rootInfo.Logger); err != nil {
logger.L().Fatal(fmt.Sprintf("supported levels: %s", strings.Join(helpers.SupportedLevels(), "/")), helpers.Error(err))
}
}
func initCacheDir(rootInfo *cautils.RootInfo) {
if rootInfo.CacheDir == getter.DefaultLocalStore {
getter.DefaultLocalStore = rootInfo.CacheDir
} else if cacheDir := os.Getenv("KS_CACHE_DIR"); cacheDir != "" {
getter.DefaultLocalStore = cacheDir
} else {
return // using default cache dir location
}
logger.L().Debug("cache dir updated", helpers.String("path", getter.DefaultLocalStore))
}
func initEnvironment(rootInfo *cautils.RootInfo) {
if armoBEURLsDep != "" {
armoBEURLs = armoBEURLsDep
}
urlSlices := strings.Split(armoBEURLs, ",")
if len(urlSlices) != 1 && len(urlSlices) < 3 {
logger.L().Fatal("expected at least 3 URLs (report, api, frontend, auth)")
}
switch len(urlSlices) {
case 1:
switch urlSlices[0] {
case "dev", "development":
getter.SetARMOAPIConnector(getter.NewARMOAPIDev())
case "stage", "staging":
getter.SetARMOAPIConnector(getter.NewARMOAPIStaging())
case "":
getter.SetARMOAPIConnector(getter.NewARMOAPIProd())
default:
logger.L().Fatal("--environment flag usage: " + envFlagUsage)
}
case 2:
logger.L().Fatal("--environment flag usage: " + envFlagUsage)
case 3, 4:
var armoAUTHURL string
armoERURL := urlSlices[0] // mandatory
armoBEURL := urlSlices[1] // mandatory
armoFEURL := urlSlices[2] // mandatory
if len(urlSlices) <= 4 {
armoAUTHURL = urlSlices[3]
}
getter.SetARMOAPIConnector(getter.NewARMOAPICustomized(armoERURL, armoBEURL, armoFEURL, armoAUTHURL))
}
}

View File

@@ -6,9 +6,9 @@ import (
"os"
"strings"
"github.com/armosec/kubescape/cautils"
"github.com/armosec/kubescape/cautils/logger"
"github.com/armosec/kubescape/clihandler"
"github.com/armosec/kubescape/core/cautils"
"github.com/armosec/kubescape/core/cautils/logger"
"github.com/armosec/kubescape/core/meta"
"github.com/armosec/opa-utils/reporthandling"
"github.com/spf13/cobra"
)
@@ -32,7 +32,7 @@ var (
)
// controlCmd represents the control command
func getControlCmd() *cobra.Command {
func getControlCmd(ks meta.IKubescape, scanInfo *cautils.ScanInfo) *cobra.Command {
return &cobra.Command{
Use: "control <control names list>/<control ids list>",
Short: "The controls you wish to use. Run 'kubescape list controls' for the list of supported controls",
@@ -53,7 +53,6 @@ func getControlCmd() *cobra.Command {
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
var scanInfo cautils.ScanInfo
// flagValidationControl(scanInfo)
scanInfo.PolicyIdentifier = []reporthandling.PolicyIdentifier{}
@@ -85,7 +84,7 @@ func getControlCmd() *cobra.Command {
scanInfo.FrameworkScan = false
results, err := clihandler.Scan(&scanInfo)
results, err := ks.Scan(scanInfo)
if err != nil {
logger.L().Fatal(err.Error())
}

View File

@@ -6,9 +6,9 @@ import (
"os"
"strings"
"github.com/armosec/kubescape/cautils"
"github.com/armosec/kubescape/cautils/logger"
"github.com/armosec/kubescape/clihandler"
"github.com/armosec/kubescape/core/cautils"
"github.com/armosec/kubescape/core/cautils/logger"
"github.com/armosec/kubescape/core/meta"
"github.com/armosec/opa-utils/reporthandling"
"github.com/spf13/cobra"
)
@@ -34,7 +34,7 @@ var (
`
)
func getFrameworkCmd() *cobra.Command {
func getFrameworkCmd(ks meta.IKubescape, scanInfo *cautils.ScanInfo) *cobra.Command {
return &cobra.Command{
Use: "framework <framework names list> [`<glob pattern>`/`-`] [flags]",
@@ -57,9 +57,8 @@ func getFrameworkCmd() *cobra.Command {
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
var scanInfo cautils.ScanInfo
flagValidationFramework(&scanInfo)
flagValidationFramework(scanInfo)
scanInfo.FrameworkScan = true
var frameworks []string
@@ -94,7 +93,7 @@ func getFrameworkCmd() *cobra.Command {
scanInfo.SetPolicyIdentifiers(frameworks, reporthandling.KindFramework)
results, err := clihandler.Scan(&scanInfo)
results, err := ks.Scan(scanInfo)
if err != nil {
logger.L().Fatal(err.Error())
}

View File

@@ -2,7 +2,8 @@ package scan
import (
"github.com/armosec/k8s-interface/k8sinterface"
"github.com/armosec/kubescape/cautils"
"github.com/armosec/kubescape/core/cautils"
"github.com/armosec/kubescape/core/meta"
"github.com/spf13/cobra"
)
@@ -26,7 +27,7 @@ var scanCmdExamples = `
`
func GetScanCommand() *cobra.Command {
func GetScanCommand(ks meta.IKubescape) *cobra.Command {
var scanInfo cautils.ScanInfo
// scanCmd represents the scan command
@@ -39,7 +40,7 @@ func GetScanCommand() *cobra.Command {
if len(args) > 0 {
if args[0] != "framework" && args[0] != "control" {
scanInfo.ScanAll = true
return getFrameworkCmd().RunE(cmd, append([]string{"all"}, args...))
return getFrameworkCmd(ks, &scanInfo).RunE(cmd, append([]string{"all"}, args...))
}
}
return nil
@@ -48,7 +49,7 @@ func GetScanCommand() *cobra.Command {
if len(args) == 0 {
scanInfo.ScanAll = true
return getFrameworkCmd().RunE(cmd, []string{"all"})
return getFrameworkCmd(ks, &scanInfo).RunE(cmd, []string{"all"})
}
return nil
},
@@ -56,7 +57,7 @@ func GetScanCommand() *cobra.Command {
k8sinterface.SetClusterContextName(scanInfo.KubeContext)
},
PostRun: func(cmd *cobra.Command, args []string) {
k8sinterface.SetClusterContextName(scanInfo.KubeContext)
// TODO - revert context
},
}
@@ -74,12 +75,12 @@ func GetScanCommand() *cobra.Command {
scanCmd.PersistentFlags().BoolVar(&scanInfo.VerboseMode, "verbose", false, "Display all of the input resources and not only failed resources")
scanCmd.PersistentFlags().BoolVar(&scanInfo.UseDefault, "use-default", false, "Load local policy object from default path. If not used will download latest")
scanCmd.PersistentFlags().StringSliceVar(&scanInfo.UseFrom, "use-from", nil, "Load local policy object from specified path. If not used will download latest")
scanCmd.PersistentFlags().BoolVarP(&scanInfo.Silent, "silent", "s", false, "Silent progress messages")
scanCmd.PersistentFlags().BoolVarP(&scanInfo.Submit, "submit", "", false, "Send the scan results to ARMO management portal where you can see the results in a user-friendly UI, choose your preferred compliance framework, check risk results history and trends, manage exceptions, get remediation recommendations and much more. By default the results are not submitted")
scanCmd.PersistentFlags().StringVar(&scanInfo.HostSensorYamlPath, "host-scan-yaml", "", "Override default host sensor DaemonSet. Use this flag cautiously")
scanCmd.PersistentFlags().StringVar(&scanInfo.HostSensorYamlPath, "host-scan-yaml", "", "Override default host scanner DaemonSet. Use this flag cautiously")
scanCmd.PersistentFlags().StringVar(&scanInfo.FormatVersion, "format-version", "v1", "Output object can be differnet between versions, this is for maintaining backward and forward compatibility. Supported:'v1'/'v2'")
// Deprecated flags - remove 1.May.2022
scanCmd.PersistentFlags().BoolVarP(&scanInfo.Silent, "silent", "s", false, "Silent progress messages")
scanCmd.PersistentFlags().MarkDeprecated("silent", "use '--logger' flag instead. Flag will be removed at 1.May.2022")
// hidden flags
@@ -91,8 +92,8 @@ func GetScanCommand() *cobra.Command {
hostF.NoOptDefVal = "true"
hostF.DefValue = "false, for no TTY in stdin"
scanCmd.AddCommand(getControlCmd())
scanCmd.AddCommand(getFrameworkCmd())
scanCmd.AddCommand(getControlCmd(ks, &scanInfo))
scanCmd.AddCommand(getFrameworkCmd(ks, &scanInfo))
return scanCmd
}

View File

@@ -3,12 +3,14 @@ package submit
import (
"fmt"
"github.com/armosec/kubescape/cautils/logger"
"github.com/armosec/kubescape/clihandler"
"github.com/armosec/kubescape/core/cautils/logger"
"github.com/armosec/kubescape/core/meta"
metav1 "github.com/armosec/kubescape/core/meta/datastructures/v1"
"github.com/spf13/cobra"
)
func getExceptionsCmd() *cobra.Command {
func getExceptionsCmd(ks meta.IKubescape, submitInfo *metav1.Submit) *cobra.Command {
return &cobra.Command{
Use: "exceptions <full path to exceptins file>",
Short: "Submit exceptions to the Kubescape SaaS version",
@@ -19,7 +21,7 @@ func getExceptionsCmd() *cobra.Command {
return nil
},
Run: func(cmd *cobra.Command, args []string) {
if err := clihandler.SubmitExceptions(submitInfo.Account, args[0]); err != nil {
if err := ks.SubmitExceptions(submitInfo.Account, args[0]); err != nil {
logger.L().Fatal(err.Error())
}
},

View File

@@ -2,19 +2,22 @@ package submit
import (
"github.com/armosec/k8s-interface/k8sinterface"
"github.com/armosec/kubescape/cautils"
"github.com/armosec/kubescape/cautils/getter"
"github.com/armosec/kubescape/cautils/logger"
"github.com/armosec/kubescape/cautils/logger/helpers"
"github.com/armosec/kubescape/clihandler"
"github.com/armosec/kubescape/clihandler/cliinterfaces"
reporterv1 "github.com/armosec/kubescape/resultshandling/reporter/v1"
"github.com/armosec/kubescape/core/cautils"
"github.com/armosec/kubescape/core/cautils/getter"
"github.com/armosec/kubescape/core/cautils/logger"
"github.com/armosec/kubescape/core/cautils/logger/helpers"
"github.com/armosec/kubescape/core/meta"
"github.com/armosec/kubescape/core/meta/cliinterfaces"
v1 "github.com/armosec/kubescape/core/meta/datastructures/v1"
reporterv1 "github.com/armosec/kubescape/core/pkg/resultshandling/reporter/v1"
"github.com/armosec/rbac-utils/rbacscanner"
"github.com/spf13/cobra"
)
// getRBACCmd represents the RBAC command
func getRBACCmd() *cobra.Command {
func getRBACCmd(ks meta.IKubescape, submitInfo *v1.Submit) *cobra.Command {
return &cobra.Command{
Use: "rbac \nExample:\n$ kubescape submit rbac",
Short: "Submit cluster's Role-Based Access Control(RBAC)",
@@ -41,7 +44,7 @@ func getRBACCmd() *cobra.Command {
Reporter: r,
}
if err := clihandler.Submit(submitInterfaces); err != nil {
if err := ks.Submit(submitInterfaces); err != nil {
logger.L().Fatal(err.Error())
}
return nil

View File

@@ -7,13 +7,15 @@ import (
"time"
"github.com/armosec/k8s-interface/workloadinterface"
"github.com/armosec/kubescape/cautils/logger"
"github.com/armosec/kubescape/cautils/logger/helpers"
"github.com/armosec/kubescape/clihandler"
"github.com/armosec/kubescape/clihandler/cliinterfaces"
"github.com/armosec/kubescape/resultshandling/reporter"
reporterv1 "github.com/armosec/kubescape/resultshandling/reporter/v1"
reporterv2 "github.com/armosec/kubescape/resultshandling/reporter/v2"
"github.com/armosec/kubescape/core/cautils/logger"
"github.com/armosec/kubescape/core/cautils/logger/helpers"
"github.com/armosec/kubescape/core/meta"
"github.com/armosec/kubescape/core/meta/cliinterfaces"
v1 "github.com/armosec/kubescape/core/meta/datastructures/v1"
"github.com/armosec/kubescape/core/pkg/resultshandling/reporter"
reporterv1 "github.com/armosec/kubescape/core/pkg/resultshandling/reporter/v1"
reporterv2 "github.com/armosec/kubescape/core/pkg/resultshandling/reporter/v2"
"github.com/armosec/opa-utils/reporthandling"
"github.com/google/uuid"
"github.com/spf13/cobra"
@@ -54,7 +56,7 @@ func (resultsObject *ResultsObject) ListAllResources() (map[string]workloadinter
return map[string]workloadinterface.IMetadata{}, nil
}
func getResultsCmd() *cobra.Command {
func getResultsCmd(ks meta.IKubescape, submitInfo *v1.Submit) *cobra.Command {
var resultsCmd = &cobra.Command{
Use: "results <json file>\nExample:\n$ kubescape submit results path/to/results.json --format-version v2",
Short: "Submit a pre scanned results file. The file must be in json format",
@@ -90,7 +92,7 @@ func getResultsCmd() *cobra.Command {
Reporter: r,
}
if err := clihandler.Submit(submitInterfaces); err != nil {
if err := ks.Submit(submitInterfaces); err != nil {
logger.L().Fatal(err.Error())
}
return nil

View File

@@ -1,17 +1,18 @@
package submit
import (
"github.com/armosec/kubescape/clihandler/cliobjects"
"github.com/armosec/kubescape/core/meta"
metav1 "github.com/armosec/kubescape/core/meta/datastructures/v1"
"github.com/spf13/cobra"
)
var submitInfo cliobjects.Submit
var submitCmdExamples = `
`
func GetSubmitCmd() *cobra.Command {
func GetSubmitCmd(ks meta.IKubescape) *cobra.Command {
var submitInfo metav1.Submit
submitCmd := &cobra.Command{
Use: "submit <command>",
Short: "Submit an object to the Kubescape SaaS version",
@@ -21,9 +22,9 @@ func GetSubmitCmd() *cobra.Command {
}
submitCmd.PersistentFlags().StringVarP(&submitInfo.Account, "account", "", "", "Armo portal account ID. Default will load account ID from configMap or config file")
submitCmd.AddCommand(getExceptionsCmd())
submitCmd.AddCommand(getResultsCmd())
submitCmd.AddCommand(getRBACCmd())
submitCmd.AddCommand(getExceptionsCmd(ks, &submitInfo))
submitCmd.AddCommand(getResultsCmd(ks, &submitInfo))
submitCmd.AddCommand(getRBACCmd(ks, &submitInfo))
return submitCmd
}

View File

@@ -4,7 +4,7 @@ import (
"fmt"
"os"
"github.com/armosec/kubescape/cautils"
"github.com/armosec/kubescape/core/cautils"
"github.com/spf13/cobra"
)

14
core/README.md Normal file
View File

@@ -0,0 +1,14 @@
# Kubescape core package
```go
// initialize kubescape
ks := core.NewKubescape()
// scan cluster
results, err := ks.Scan(&cautils.ScanInfo{})
// convert scan results to json
jsonRes, err := results.ToJson()
```

View File

@@ -10,7 +10,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/armosec/k8s-interface/k8sinterface"
"github.com/armosec/kubescape/cautils/getter"
"github.com/armosec/kubescape/core/cautils/getter"
corev1 "k8s.io/api/core/v1"
)

View File

@@ -4,7 +4,7 @@ import (
"os"
"time"
"github.com/briandowns/spinner"
spinnerpkg "github.com/briandowns/spinner"
"github.com/fatih/color"
"github.com/mattn/go-isatty"
)
@@ -18,18 +18,24 @@ var SimpleDisplay = color.New().FprintfFunc()
var SuccessDisplay = color.New(color.Bold, color.FgHiGreen).FprintfFunc()
var DescriptionDisplay = color.New(color.Faint, color.FgWhite).FprintfFunc()
var Spinner *spinner.Spinner
var spinner *spinnerpkg.Spinner
func StartSpinner() {
if spinner != nil {
if !spinner.Active() {
spinner.Start()
}
return
}
if isatty.IsTerminal(os.Stdout.Fd()) {
Spinner = spinner.New(spinner.CharSets[7], 100*time.Millisecond) // Build our new spinner
Spinner.Start()
spinner = spinnerpkg.New(spinnerpkg.CharSets[7], 100*time.Millisecond) // Build our new spinner
spinner.Start()
}
}
func StopSpinner() {
if Spinner == nil {
if spinner == nil || !spinner.Active() {
return
}
Spinner.Stop()
spinner.Stop()
}

View File

@@ -9,7 +9,7 @@ import (
"strings"
"github.com/armosec/k8s-interface/workloadinterface"
"github.com/armosec/kubescape/cautils/logger"
"github.com/armosec/kubescape/core/cautils/logger"
"github.com/armosec/opa-utils/objectsenvelopes"
"gopkg.in/yaml.v2"
)

View File

@@ -11,7 +11,7 @@ import (
func onlineBoutiquePath() string {
o, _ := os.Getwd()
return filepath.Join(filepath.Dir(o), "examples/online-boutique/*")
return filepath.Join(filepath.Dir(o), "../examples/online-boutique/*")
}
func TestListFiles(t *testing.T) {

View File

@@ -10,8 +10,8 @@ import (
"time"
"github.com/armosec/armoapi-go/armotypes"
"github.com/armosec/kubescape/cautils/logger"
"github.com/armosec/kubescape/cautils/logger/helpers"
"github.com/armosec/kubescape/core/cautils/logger"
"github.com/armosec/kubescape/core/cautils/logger/helpers"
"github.com/armosec/opa-utils/reporthandling"
)

View File

@@ -4,10 +4,10 @@ import (
"os"
"strings"
"github.com/armosec/kubescape/cautils/logger/helpers"
"github.com/armosec/kubescape/cautils/logger/nonelogger"
"github.com/armosec/kubescape/cautils/logger/prettylogger"
"github.com/armosec/kubescape/cautils/logger/zaplogger"
"github.com/armosec/kubescape/core/cautils/logger/helpers"
"github.com/armosec/kubescape/core/cautils/logger/nonelogger"
"github.com/armosec/kubescape/core/cautils/logger/prettylogger"
"github.com/armosec/kubescape/core/cautils/logger/zaplogger"
)
type ILogger interface {

View File

@@ -3,7 +3,7 @@ package nonelogger
import (
"os"
"github.com/armosec/kubescape/cautils/logger/helpers"
"github.com/armosec/kubescape/core/cautils/logger/helpers"
)
const LoggerName string = "none"

View File

@@ -3,7 +3,7 @@ package prettylogger
import (
"io"
"github.com/armosec/kubescape/cautils/logger/helpers"
"github.com/armosec/kubescape/core/cautils/logger/helpers"
"github.com/fatih/color"
)

View File

@@ -5,7 +5,7 @@ import (
"os"
"sync"
"github.com/armosec/kubescape/cautils/logger/helpers"
"github.com/armosec/kubescape/core/cautils/logger/helpers"
)
const LoggerName string = "pretty"

View File

@@ -3,7 +3,7 @@ package zaplogger
import (
"os"
"github.com/armosec/kubescape/cautils/logger/helpers"
"github.com/armosec/kubescape/core/cautils/logger/helpers"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)

View File

@@ -8,9 +8,9 @@ import (
"path/filepath"
"strings"
"github.com/armosec/kubescape/cautils/getter"
"github.com/armosec/kubescape/cautils/logger"
"github.com/armosec/kubescape/cautils/logger/helpers"
"github.com/armosec/kubescape/core/cautils/getter"
"github.com/armosec/kubescape/core/cautils/logger"
"github.com/armosec/kubescape/core/cautils/logger/helpers"
"github.com/armosec/opa-utils/reporthandling"
)
@@ -60,32 +60,33 @@ type RootInfo struct {
DisableColor bool // Disable Color
}
// TODO - UPDATE
type ScanInfo struct {
Getters
PolicyIdentifier []reporthandling.PolicyIdentifier
UseExceptions string // Load file with exceptions configuration
ControlsInputs string // Load file with inputs for controls
UseFrom []string // Load framework from local file (instead of download). Use when running offline
UseDefault bool // Load framework from cached file (instead of download). Use when running offline
UseArtifactsFrom string // Load artifacts from local path. Use when running offline
VerboseMode bool // Display all of the input resources and not only failed resources
Format string // Format results (table, json, junit ...)
Output string // Store results in an output file, Output file name
FormatVersion string // Output object can be differnet between versions, this is for testing and backward compatibility
ExcludedNamespaces string // used for host sensor namespace
IncludeNamespaces string // DEPRECATED?
InputPatterns []string // Yaml files input patterns
Silent bool // Silent mode - Do not print progress logs
FailThreshold float32 // Failure score threshold
Submit bool // Submit results to Armo BE
ReportID string // Report id of the current scan
HostSensorEnabled BoolPtrFlag // Deploy ARMO K8s host sensor to collect data from certain controls
HostSensorYamlPath string // Path to hostsensor file
Local bool // Do not submit results
Account string // account ID
KubeContext string // context name
FrameworkScan bool // false if scanning control
ScanAll bool // true if scan all frameworks
Getters // TODO - remove from object
PolicyIdentifier []reporthandling.PolicyIdentifier // TODO - remove from object
UseExceptions string // Load file with exceptions configuration
ControlsInputs string // Load file with inputs for controls
UseFrom []string // Load framework from local file (instead of download). Use when running offline
UseDefault bool // Load framework from cached file (instead of download). Use when running offline
UseArtifactsFrom string // Load artifacts from local path. Use when running offline
VerboseMode bool // Display all of the input resources and not only failed resources
Format string // Format results (table, json, junit ...)
Output string // Store results in an output file, Output file name
FormatVersion string // Output object can be differnet between versions, this is for testing and backward compatibility
ExcludedNamespaces string // used for host scanner namespace
IncludeNamespaces string // DEPRECATED?
InputPatterns []string // Yaml files input patterns
Silent bool // Silent mode - Do not print progress logs
FailThreshold float32 // Failure score threshold
Submit bool // Submit results to Armo BE
ReportID string // Report id of the current scan
HostSensorEnabled BoolPtrFlag // Deploy ARMO K8s host scanner to collect data from certain controls
HostSensorYamlPath string // Path to hostsensor file
Local bool // Do not submit results
Account string // account ID
KubeContext string // context name
FrameworkScan bool // false if scanning control
ScanAll bool // true if scan all frameworks
}
type Getters struct {

View File

@@ -6,14 +6,15 @@ import (
"net/http"
"os"
"github.com/armosec/kubescape/cautils/getter"
"github.com/armosec/kubescape/cautils/logger"
"github.com/armosec/kubescape/cautils/logger/helpers"
"github.com/armosec/kubescape/core/cautils/getter"
"github.com/armosec/kubescape/core/cautils/logger"
"github.com/armosec/kubescape/core/cautils/logger/helpers"
pkgutils "github.com/armosec/utils-go/utils"
"golang.org/x/mod/semver"
)
const SKIP_VERSION_CHECK = "KUBESCAPE_SKIP_UPDATE_CHECK"
const SKIP_VERSION_CHECK_DEPRECATED = "KUBESCAPE_SKIP_UPDATE_CHECK"
const SKIP_VERSION_CHECK = "KS_SKIP_UPDATE_CHECK"
var BuildNumber string
@@ -29,6 +30,8 @@ func NewIVersionCheckHandler() IVersionCheckHandler {
}
if v, ok := os.LookupEnv(SKIP_VERSION_CHECK); ok && pkgutils.StringToBool(v) {
return NewVersionCheckHandlerMock()
} else if v, ok := os.LookupEnv(SKIP_VERSION_CHECK_DEPRECATED); ok && pkgutils.StringToBool(v) {
return NewVersionCheckHandlerMock()
}
return NewVersionCheckHandler()
}

37
core/core/cachedconfig.go Normal file
View File

@@ -0,0 +1,37 @@
package core
import (
"fmt"
metav1 "github.com/armosec/kubescape/core/meta/datastructures/v1"
)
func (ks *Kubescape) SetCachedConfig(setConfig *metav1.SetConfig) error {
tenant := getTenantConfig("", "", getKubernetesApi())
if setConfig.Account != "" {
tenant.GetConfigObj().AccountID = setConfig.Account
}
if setConfig.SecretKey != "" {
tenant.GetConfigObj().SecretKey = setConfig.SecretKey
}
if setConfig.ClientID != "" {
tenant.GetConfigObj().ClientID = setConfig.ClientID
}
return tenant.UpdateCachedConfig()
}
// View cached configurations
func (ks *Kubescape) ViewCachedConfig(viewConfig *metav1.ViewConfig) error {
tenant := getTenantConfig("", "", getKubernetesApi()) // change k8sinterface
fmt.Fprintf(viewConfig.Writer, "%s\n", tenant.GetConfigObj().Config())
return nil
}
func (ks *Kubescape) DeleteCachedConfig(deleteConfig *metav1.DeleteConfig) error {
tenant := getTenantConfig("", "", getKubernetesApi()) // change k8sinterface
return tenant.DeleteCachedConfig()
}

View File

@@ -1,17 +1,18 @@
package clihandler
package core
import (
"fmt"
"github.com/armosec/kubescape/cautils/getter"
"github.com/armosec/kubescape/cautils/logger"
"github.com/armosec/kubescape/cautils/logger/helpers"
"github.com/armosec/kubescape/core/cautils/getter"
"github.com/armosec/kubescape/core/cautils/logger"
"github.com/armosec/kubescape/core/cautils/logger/helpers"
v1 "github.com/armosec/kubescape/core/meta/datastructures/v1"
)
func DeleteExceptions(accountID string, exceptions []string) error {
func (ks *Kubescape) DeleteExceptions(delExceptions *v1.DeleteExceptions) error {
// load cached config
getTenantConfig(accountID, "", getKubernetesApi())
getTenantConfig(delExceptions.Account, "", getKubernetesApi())
// login kubescape SaaS
armoAPI := getter.GetArmoAPIConnector()
@@ -19,8 +20,8 @@ func DeleteExceptions(accountID string, exceptions []string) error {
return err
}
for i := range exceptions {
exceptionName := exceptions[i]
for i := range delExceptions.Exceptions {
exceptionName := delExceptions.Exceptions[i]
if exceptionName == "" {
continue
}

View File

@@ -1,4 +1,4 @@
package clihandler
package core
import (
"fmt"
@@ -6,13 +6,13 @@ import (
"strings"
"github.com/armosec/armoapi-go/armotypes"
"github.com/armosec/kubescape/cautils"
"github.com/armosec/kubescape/cautils/getter"
"github.com/armosec/kubescape/cautils/logger"
"github.com/armosec/kubescape/cautils/logger/helpers"
"github.com/armosec/kubescape/core/cautils/getter"
"github.com/armosec/kubescape/core/cautils/logger"
"github.com/armosec/kubescape/core/cautils/logger/helpers"
metav1 "github.com/armosec/kubescape/core/meta/datastructures/v1"
)
var downloadFunc = map[string]func(*cautils.DownloadInfo) error{
var downloadFunc = map[string]func(*metav1.DownloadInfo) error{
"controls-inputs": downloadConfigInputs,
"exceptions": downloadExceptions,
"control": downloadControl,
@@ -28,7 +28,7 @@ func DownloadSupportCommands() []string {
return commands
}
func CliDownload(downloadInfo *cautils.DownloadInfo) error {
func (ks *Kubescape) Download(downloadInfo *metav1.DownloadInfo) error {
setPathandFilename(downloadInfo)
if err := downloadArtifact(downloadInfo, downloadFunc); err != nil {
return err
@@ -36,7 +36,7 @@ func CliDownload(downloadInfo *cautils.DownloadInfo) error {
return nil
}
func downloadArtifact(downloadInfo *cautils.DownloadInfo, downloadArtifactFunc map[string]func(*cautils.DownloadInfo) error) error {
func downloadArtifact(downloadInfo *metav1.DownloadInfo, downloadArtifactFunc map[string]func(*metav1.DownloadInfo) error) error {
if f, ok := downloadArtifactFunc[downloadInfo.Target]; ok {
if err := f(downloadInfo); err != nil {
return err
@@ -46,7 +46,7 @@ func downloadArtifact(downloadInfo *cautils.DownloadInfo, downloadArtifactFunc m
return fmt.Errorf("unknown command to download")
}
func setPathandFilename(downloadInfo *cautils.DownloadInfo) {
func setPathandFilename(downloadInfo *metav1.DownloadInfo) {
if downloadInfo.Path == "" {
downloadInfo.Path = getter.GetDefaultPath("")
} else {
@@ -60,22 +60,22 @@ func setPathandFilename(downloadInfo *cautils.DownloadInfo) {
}
}
func downloadArtifacts(downloadInfo *cautils.DownloadInfo) error {
func downloadArtifacts(downloadInfo *metav1.DownloadInfo) error {
downloadInfo.FileName = ""
var artifacts = map[string]func(*cautils.DownloadInfo) error{
var artifacts = map[string]func(*metav1.DownloadInfo) error{
"controls-inputs": downloadConfigInputs,
"exceptions": downloadExceptions,
"framework": downloadFramework,
}
for artifact := range artifacts {
if err := downloadArtifact(&cautils.DownloadInfo{Target: artifact, Path: downloadInfo.Path, FileName: fmt.Sprintf("%s.json", artifact)}, artifacts); err != nil {
if err := downloadArtifact(&metav1.DownloadInfo{Target: artifact, Path: downloadInfo.Path, FileName: fmt.Sprintf("%s.json", artifact)}, artifacts); err != nil {
logger.L().Error("error downloading", helpers.String("artifact", artifact), helpers.Error(err))
}
}
return nil
}
func downloadConfigInputs(downloadInfo *cautils.DownloadInfo) error {
func downloadConfigInputs(downloadInfo *metav1.DownloadInfo) error {
tenant := getTenantConfig(downloadInfo.Account, "", getKubernetesApi())
controlsInputsGetter := getConfigInputsGetter(downloadInfo.Name, tenant.GetAccountID(), nil)
@@ -95,7 +95,7 @@ func downloadConfigInputs(downloadInfo *cautils.DownloadInfo) error {
return nil
}
func downloadExceptions(downloadInfo *cautils.DownloadInfo) error {
func downloadExceptions(downloadInfo *metav1.DownloadInfo) error {
var err error
tenant := getTenantConfig(downloadInfo.Account, "", getKubernetesApi())
@@ -119,7 +119,7 @@ func downloadExceptions(downloadInfo *cautils.DownloadInfo) error {
return nil
}
func downloadFramework(downloadInfo *cautils.DownloadInfo) error {
func downloadFramework(downloadInfo *metav1.DownloadInfo) error {
tenant := getTenantConfig(downloadInfo.Account, "", getKubernetesApi())
@@ -158,7 +158,7 @@ func downloadFramework(downloadInfo *cautils.DownloadInfo) error {
return nil
}
func downloadControl(downloadInfo *cautils.DownloadInfo) error {
func downloadControl(downloadInfo *metav1.DownloadInfo) error {
tenant := getTenantConfig(downloadInfo.Account, "", getKubernetesApi())

View File

@@ -1,18 +1,18 @@
package clihandler
package core
import (
"fmt"
"os"
"github.com/armosec/k8s-interface/k8sinterface"
"github.com/armosec/kubescape/cautils"
"github.com/armosec/kubescape/cautils/getter"
"github.com/armosec/kubescape/cautils/logger"
"github.com/armosec/kubescape/cautils/logger/helpers"
"github.com/armosec/kubescape/hostsensorutils"
"github.com/armosec/kubescape/resourcehandler"
"github.com/armosec/kubescape/resultshandling/reporter"
reporterv2 "github.com/armosec/kubescape/resultshandling/reporter/v2"
"github.com/armosec/kubescape/core/cautils"
"github.com/armosec/kubescape/core/cautils/getter"
"github.com/armosec/kubescape/core/cautils/logger"
"github.com/armosec/kubescape/core/cautils/logger/helpers"
"github.com/armosec/kubescape/core/pkg/hostsensorutils"
"github.com/armosec/kubescape/core/pkg/resourcehandler"
"github.com/armosec/kubescape/core/pkg/resultshandling/reporter"
reporterv2 "github.com/armosec/kubescape/core/pkg/resultshandling/reporter/v2"
"github.com/armosec/opa-utils/reporthandling"
"github.com/armosec/rbac-utils/rbacscanner"
@@ -82,15 +82,15 @@ func getHostSensorHandler(scanInfo *cautils.ScanInfo, k8s *k8sinterface.Kubernet
}
hasHostSensorControls := true
// we need to determined which controls needs host sensor
// we need to determined which controls needs host scanner
if scanInfo.HostSensorEnabled.Get() == nil && hasHostSensorControls {
scanInfo.HostSensorEnabled.SetBool(askUserForHostSensor())
scanInfo.HostSensorEnabled.SetBool(false) // default - do not run host scanner
logger.L().Warning("Kubernetes cluster nodes scanning is disabled. This is required to collect valuable data for certain controls. You can enable it using the --enable-host-scan flag")
}
if hostSensorVal := scanInfo.HostSensorEnabled.Get(); hostSensorVal != nil && *hostSensorVal {
hostSensorHandler, err := hostsensorutils.NewHostSensorHandler(k8s, scanInfo.HostSensorYamlPath)
if err != nil {
logger.L().Warning(fmt.Sprintf("failed to create host sensor: %s", err.Error()))
logger.L().Warning(fmt.Sprintf("failed to create host scanner: %s", err.Error()))
return &hostsensorutils.HostSensorHandlerMock{}
}
return hostSensorHandler

7
core/core/kscore.go Normal file
View File

@@ -0,0 +1,7 @@
package core
type Kubescape struct{}
func NewKubescape() *Kubescape {
return &Kubescape{}
}

View File

@@ -1,4 +1,4 @@
package clihandler
package core
import (
"encoding/json"
@@ -6,29 +6,29 @@ import (
"sort"
"strings"
"github.com/armosec/kubescape/cautils/getter"
"github.com/armosec/kubescape/clihandler/cliobjects"
"github.com/armosec/kubescape/core/cautils/getter"
metav1 "github.com/armosec/kubescape/core/meta/datastructures/v1"
)
var listFunc = map[string]func(*cliobjects.ListPolicies) ([]string, error){
var listFunc = map[string]func(*metav1.ListPolicies) ([]string, error){
"controls": listControls,
"frameworks": listFrameworks,
"exceptions": listExceptions,
}
var listFormatFunc = map[string]func(*cliobjects.ListPolicies, []string){
var listFormatFunc = map[string]func(*metav1.ListPolicies, []string){
"pretty-print": prettyPrintListFormat,
"json": jsonListFormat,
}
func ListSupportCommands() []string {
func ListSupportActions() []string {
commands := []string{}
for k := range listFunc {
commands = append(commands, k)
}
return commands
}
func CliList(listPolicies *cliobjects.ListPolicies) error {
func (ks *Kubescape) List(listPolicies *metav1.ListPolicies) error {
if f, ok := listFunc[listPolicies.Target]; ok {
policies, err := f(listPolicies)
if err != nil {
@@ -43,14 +43,14 @@ func CliList(listPolicies *cliobjects.ListPolicies) error {
return fmt.Errorf("unknown command to download")
}
func listFrameworks(listPolicies *cliobjects.ListPolicies) ([]string, error) {
func listFrameworks(listPolicies *metav1.ListPolicies) ([]string, error) {
tenant := getTenantConfig(listPolicies.Account, "", getKubernetesApi()) // change k8sinterface
g := getPolicyGetter(nil, tenant.GetAccountID(), true, nil)
return listFrameworksNames(g), nil
}
func listControls(listPolicies *cliobjects.ListPolicies) ([]string, error) {
func listControls(listPolicies *metav1.ListPolicies) ([]string, error) {
tenant := getTenantConfig(listPolicies.Account, "", getKubernetesApi()) // change k8sinterface
g := getPolicyGetter(nil, tenant.GetAccountID(), false, nil)
@@ -61,8 +61,8 @@ func listControls(listPolicies *cliobjects.ListPolicies) ([]string, error) {
return g.ListControls(l)
}
func listExceptions(listPolicies *cliobjects.ListPolicies) ([]string, error) {
// load tenant config
func listExceptions(listPolicies *metav1.ListPolicies) ([]string, error) {
// load tenant metav1
getTenantConfig(listPolicies.Account, "", getKubernetesApi())
var exceptionsNames []string
@@ -77,12 +77,12 @@ func listExceptions(listPolicies *cliobjects.ListPolicies) ([]string, error) {
return exceptionsNames, nil
}
func prettyPrintListFormat(listPolicies *cliobjects.ListPolicies, policies []string) {
func prettyPrintListFormat(listPolicies *metav1.ListPolicies, policies []string) {
sep := "\n * "
fmt.Printf("Supported %s:%s%s\n", listPolicies.Target, sep, strings.Join(policies, sep))
}
func jsonListFormat(listPolicies *cliobjects.ListPolicies, policies []string) {
func jsonListFormat(listPolicies *metav1.ListPolicies, policies []string) {
j, _ := json.MarshalIndent(policies, "", " ")
fmt.Printf("%s\n", j)
}

View File

@@ -1,27 +1,25 @@
package clihandler
package core
import (
"fmt"
"io/fs"
"os"
"github.com/armosec/armoapi-go/armotypes"
"github.com/armosec/k8s-interface/k8sinterface"
"github.com/armosec/kubescape/resultshandling/printer"
"github.com/armosec/kubescape/cautils"
"github.com/armosec/kubescape/cautils/getter"
"github.com/armosec/kubescape/cautils/logger"
"github.com/armosec/kubescape/cautils/logger/helpers"
"github.com/armosec/kubescape/hostsensorutils"
"github.com/armosec/kubescape/opaprocessor"
"github.com/armosec/kubescape/policyhandler"
"github.com/armosec/kubescape/resourcehandler"
"github.com/armosec/kubescape/resultshandling"
"github.com/armosec/kubescape/resultshandling/reporter"
"github.com/armosec/kubescape/core/cautils"
"github.com/armosec/kubescape/core/cautils/getter"
"github.com/armosec/kubescape/core/cautils/logger"
"github.com/armosec/kubescape/core/cautils/logger/helpers"
"github.com/armosec/kubescape/core/pkg/hostsensorutils"
"github.com/armosec/kubescape/core/pkg/opaprocessor"
"github.com/armosec/kubescape/core/pkg/policyhandler"
"github.com/armosec/kubescape/core/pkg/resourcehandler"
"github.com/armosec/kubescape/core/pkg/resultshandling"
"github.com/armosec/kubescape/core/pkg/resultshandling/printer"
"github.com/armosec/kubescape/core/pkg/resultshandling/reporter"
"github.com/armosec/opa-utils/reporthandling"
"github.com/armosec/opa-utils/resources"
"github.com/mattn/go-isatty"
)
type componentInterfaces struct {
@@ -62,11 +60,11 @@ func getInterfaces(scanInfo *cautils.ScanInfo) componentInterfaces {
v := cautils.NewIVersionCheckHandler()
v.CheckLatestVersion(cautils.NewVersionCheckRequest(cautils.BuildNumber, policyIdentifierNames(scanInfo.PolicyIdentifier), "", scanInfo.GetScanningEnvironment()))
// ================== setup host sensor object ======================================
// ================== setup host scanner object ======================================
hostSensorHandler := getHostSensorHandler(scanInfo, k8s)
if err := hostSensorHandler.Init(); err != nil {
logger.L().Error("failed to init host sensor", helpers.Error(err))
logger.L().Error("failed to init host scanner", helpers.Error(err))
hostSensorHandler = &hostsensorutils.HostSensorHandlerMock{}
}
// excluding hostsensor namespace
@@ -105,7 +103,7 @@ func getInterfaces(scanInfo *cautils.ScanInfo) componentInterfaces {
}
}
func Scan(scanInfo *cautils.ScanInfo) (*resultshandling.ResultsHandler, error) {
func (ks *Kubescape) Scan(scanInfo *cautils.ScanInfo) (*resultshandling.ResultsHandler, error) {
logger.L().Info("ARMO security scanner starting")
// ===================== Initialization =====================
@@ -133,7 +131,7 @@ func Scan(scanInfo *cautils.ScanInfo) (*resultshandling.ResultsHandler, error) {
// remove host scanner components
defer func() {
if err := interfaces.hostSensorHandler.TearDown(); err != nil {
logger.L().Error("failed to tear down host sensor", helpers.Error(err))
logger.L().Error("failed to tear down host scanner", helpers.Error(err))
}
}()
@@ -141,7 +139,7 @@ func Scan(scanInfo *cautils.ScanInfo) (*resultshandling.ResultsHandler, error) {
// ===================== policies & resources =====================
policyHandler := policyhandler.NewPolicyHandler(interfaces.resourceHandler)
scanData, err := CollectResources(policyHandler, scanInfo)
scanData, err := collectResources(policyHandler, scanInfo)
if err != nil {
return resultsHandling, err
}
@@ -164,7 +162,8 @@ func Scan(scanInfo *cautils.ScanInfo) (*resultshandling.ResultsHandler, error) {
return resultsHandling, nil
}
func CollectResources(policyHandler *policyhandler.PolicyHandler, scanInfo *cautils.ScanInfo) (*cautils.OPASessionObj, error) {
// TODO - remove function
func collectResources(policyHandler *policyhandler.PolicyHandler, scanInfo *cautils.ScanInfo) (*cautils.OPASessionObj, error) {
policyNotification := &reporthandling.PolicyNotification{
Rules: scanInfo.PolicyIdentifier,
KubescapeNotification: reporthandling.KubescapeNotification{
@@ -183,27 +182,26 @@ func CollectResources(policyHandler *policyhandler.PolicyHandler, scanInfo *caut
default:
return nil, fmt.Errorf("notification type '%s' Unknown", policyNotification.KubescapeNotification.NotificationType)
}
return nil, nil
}
func askUserForHostSensor() bool {
return false
// 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
}
// 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

@@ -1,14 +1,14 @@
package clihandler
package core
import (
"github.com/armosec/kubescape/cautils"
"github.com/armosec/kubescape/cautils/getter"
"github.com/armosec/kubescape/cautils/logger"
"github.com/armosec/kubescape/cautils/logger/helpers"
"github.com/armosec/kubescape/clihandler/cliinterfaces"
"github.com/armosec/kubescape/core/cautils"
"github.com/armosec/kubescape/core/cautils/getter"
"github.com/armosec/kubescape/core/cautils/logger"
"github.com/armosec/kubescape/core/cautils/logger/helpers"
"github.com/armosec/kubescape/core/meta/cliinterfaces"
)
func Submit(submitInterfaces cliinterfaces.SubmitInterfaces) error {
func (ks *Kubescape) Submit(submitInterfaces cliinterfaces.SubmitInterfaces) error {
// list resources
postureReport, err := submitInterfaces.SubmitObjects.SetResourcesReport()
@@ -29,7 +29,7 @@ func Submit(submitInterfaces cliinterfaces.SubmitInterfaces) error {
return nil
}
func SubmitExceptions(accountID, excPath string) error {
func (ks *Kubescape) SubmitExceptions(accountID, excPath string) error {
logger.L().Info("submitting exceptions", helpers.String("path", excPath))
// load cached config

View File

@@ -1,37 +1,35 @@
module github.com/armosec/kubescape
module github.com/armosec/kubescape/core
go 1.17
require (
github.com/armosec/armoapi-go v0.0.57
github.com/armosec/k8s-interface v0.0.63
github.com/armosec/opa-utils v0.0.110
github.com/armosec/armoapi-go v0.0.58
github.com/armosec/k8s-interface v0.0.68
github.com/armosec/opa-utils v0.0.116
github.com/armosec/rbac-utils v0.0.14
github.com/armosec/utils-go v0.0.3
github.com/armosec/utils-k8s-go v0.0.1
github.com/briandowns/spinner v1.18.0
github.com/armosec/utils-k8s-go v0.0.3
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/google/uuid v1.3.0
github.com/gorilla/mux v1.8.0
github.com/johnfercher/maroto v0.34.0
github.com/mattn/go-isatty v0.0.14
github.com/olekukonko/tablewriter v0.0.5
github.com/open-policy-agent/opa v0.33.1
github.com/spf13/cobra v1.2.1
github.com/open-policy-agent/opa v0.38.0
github.com/stretchr/testify v1.7.0
go.uber.org/zap v1.19.1
golang.org/x/mod v0.4.2
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.22.2
k8s.io/apimachinery v0.22.2
k8s.io/client-go v0.22.2
sigs.k8s.io/yaml v1.2.0
k8s.io/api v0.23.4
k8s.io/apimachinery v0.23.4
k8s.io/client-go v0.23.4
sigs.k8s.io/yaml v1.3.0
)
require (
cloud.google.com/go v0.97.0 // indirect
cloud.google.com/go v0.99.0 // indirect
cloud.google.com/go/container v1.0.0 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.18 // indirect
@@ -54,33 +52,38 @@ require (
github.com/aws/aws-sdk-go-v2/service/sts v1.13.0 // indirect
github.com/aws/smithy-go v1.9.1 // indirect
github.com/boombuler/barcode v1.0.0 // 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/docker/docker v20.10.9+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/form3tech-oss/jwt-go v3.2.3+incompatible // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-gota/gota v0.12.0 // indirect
github.com/go-logr/logr v0.4.0 // indirect
github.com/go-logr/logr v1.2.2 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/gogo/protobuf v1.3.2 // 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.6 // 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/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/json-iterator/go v1.1.11 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/jung-kurt/gofpdf v1.4.2 // indirect
github.com/mattn/go-colorable v0.1.9 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
@@ -95,24 +98,26 @@ require (
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-20210711020723-a769d52b0f97 // indirect
golang.org/x/net v0.0.0-20210825183410-e898025ed96a // indirect
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1 // indirect
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359 // indirect
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // 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/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.59.0 // indirect
google.golang.org/api v0.62.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20211027162914-98a5263abeca // indirect
google.golang.org/grpc v1.40.0 // indirect
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa // indirect
google.golang.org/grpc v1.44.0 // indirect
google.golang.org/protobuf v1.27.1 // 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.9.0 // indirect
k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a // indirect
sigs.k8s.io/controller-runtime v0.10.2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.1.2 // indirect
k8s.io/klog/v2 v2.30.0 // indirect
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 // indirect
k8s.io/utils v0.0.0-20211116205334-6203023598ed // indirect
sigs.k8s.io/controller-runtime v0.11.1 // indirect
sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
)

1479
core/go.sum Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +0,0 @@
package core
// Scan
// List
// Download
// Config
// Submit

View File

@@ -2,8 +2,8 @@ package cliinterfaces
import (
"github.com/armosec/k8s-interface/workloadinterface"
"github.com/armosec/kubescape/cautils"
"github.com/armosec/kubescape/resultshandling/reporter"
"github.com/armosec/kubescape/core/cautils"
"github.com/armosec/kubescape/core/pkg/resultshandling/reporter"
"github.com/armosec/opa-utils/reporthandling"
)

View File

@@ -0,0 +1,16 @@
package v1
import "io"
type SetConfig struct {
Account string
ClientID string
SecretKey string
}
type ViewConfig struct {
Writer io.Writer
}
type DeleteConfig struct {
}

View File

@@ -0,0 +1,6 @@
package v1
type DeleteExceptions struct {
Account string
Exceptions []string
}

View File

@@ -1,9 +1,9 @@
package cautils
package v1
type DownloadInfo struct {
Path string // directory to save artifact. Default is "~/.kubescape/"
FileName string // can be empty
Target string // type of artifact to download
Name string // name of artifact to download
Account string // customerGUID
Account string // AccountID
}

View File

@@ -1,4 +1,4 @@
package cliobjects
package v1
type ListPolicies struct {
Target string
@@ -6,3 +6,8 @@ type ListPolicies struct {
Account string
Format string
}
type ListResponse struct {
Names []string
IDs []string
}

View File

@@ -0,0 +1,3 @@
package v1
// Add scanInfo

View File

@@ -1,4 +1,4 @@
package cliobjects
package v1
type Submit struct {
Account string

28
core/meta/ksinterface.go Normal file
View File

@@ -0,0 +1,28 @@
package meta
import (
"github.com/armosec/kubescape/core/cautils"
"github.com/armosec/kubescape/core/meta/cliinterfaces"
metav1 "github.com/armosec/kubescape/core/meta/datastructures/v1"
"github.com/armosec/kubescape/core/pkg/resultshandling"
)
type IKubescape interface {
Scan(scanInfo *cautils.ScanInfo) (*resultshandling.ResultsHandler, error) // TODO - use scanInfo from v1
// policies
List(listPolicies *metav1.ListPolicies) error // TODO - return list response
Download(downloadInfo *metav1.DownloadInfo) error // TODO - return downloaded policies
// submit
Submit(submitInterfaces cliinterfaces.SubmitInterfaces) error // TODO - func should receive object
SubmitExceptions(accountID, excPath string) error // TODO - remove
// config
SetCachedConfig(setConfig *metav1.SetConfig) error
ViewCachedConfig(viewConfig *metav1.ViewConfig) error
DeleteCachedConfig(deleteConfig *metav1.DeleteConfig) error
// delete
DeleteExceptions(deleteexceptions *metav1.DeleteExceptions) error
}

View File

@@ -10,9 +10,9 @@ import (
"github.com/armosec/k8s-interface/k8sinterface"
"github.com/armosec/k8s-interface/workloadinterface"
"github.com/armosec/kubescape/cautils"
"github.com/armosec/kubescape/cautils/logger"
"github.com/armosec/kubescape/cautils/logger/helpers"
"github.com/armosec/kubescape/core/cautils"
"github.com/armosec/kubescape/core/cautils/logger"
"github.com/armosec/kubescape/core/cautils/logger/helpers"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -71,18 +71,19 @@ func (hsh *HostSensorHandler) Init() error {
// store namespace + port
// store pod names
// make sure all pods are running, after X seconds treat has running anyway, and log an error on the pods not running yet
logger.L().Info("Installing host sensor")
logger.L().Info("Installing host scanner")
cautils.StartSpinner()
defer cautils.StopSpinner()
if err := hsh.applyYAML(); err != nil {
return fmt.Errorf("failed to apply host sensor YAML, reason: %v", err)
cautils.StopSpinner()
return fmt.Errorf("failed to apply host scanner YAML, reason: %v", err)
}
hsh.populatePodNamesToNodeNames()
if err := hsh.checkPodForEachNode(); err != nil {
logger.L().Error("failed to validate host-sensor pods status", helpers.Error(err))
}
cautils.StopSpinner()
return nil
}

View File

@@ -6,9 +6,8 @@ import (
"sync"
"github.com/armosec/k8s-interface/k8sinterface"
"github.com/armosec/kubescape/cautils"
"github.com/armosec/kubescape/cautils/logger"
"github.com/armosec/kubescape/cautils/logger/helpers"
"github.com/armosec/kubescape/core/cautils/logger"
"github.com/armosec/kubescape/core/cautils/logger/helpers"
"github.com/armosec/opa-utils/objectsenvelopes/hostsensor"
"sigs.k8s.io/yaml"
)
@@ -163,9 +162,7 @@ func (hsh *HostSensorHandler) CollectResources() ([]hostsensor.HostSensorDataEnv
return res, nil
}
logger.L().Debug("Accessing host sensor")
cautils.StartSpinner()
defer cautils.StopSpinner()
logger.L().Debug("Accessing host scanner")
kcData, err := hsh.GetKubeletConfigurations()
if err != nil {
return kcData, err
@@ -209,6 +206,6 @@ func (hsh *HostSensorHandler) CollectResources() ([]hostsensor.HostSensorDataEnv
res = append(res, kcData...)
// finish
logger.L().Debug("Done reading information from host sensor")
logger.L().Debug("Done reading information from host scanner")
return res, nil
}

Some files were not shown because too many files have changed in this diff Show More