From 43ab7dbe5fa4a000c7f438a18cf3f7e17c46e578 Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Tue, 20 Jun 2023 14:30:49 +0300 Subject: [PATCH 01/48] support loading security framework Signed-off-by: YiscahLevySilas1 --- gitregostore/gitstoremethods.go | 101 ++++++++++++++++++++++++--- gitregostore/gitstoremethods_test.go | 80 +++++++++++++++++++++ gitregostore/gitstoreutils.go | 11 ++- 3 files changed, 182 insertions(+), 10 deletions(-) diff --git a/gitregostore/gitstoremethods.go b/gitregostore/gitstoremethods.go index bba2e8bc1..8316f575d 100644 --- a/gitregostore/gitstoremethods.go +++ b/gitregostore/gitstoremethods.go @@ -9,12 +9,19 @@ import ( "github.com/go-gota/gota/series" opapolicy "github.com/kubescape/opa-utils/reporthandling" "github.com/kubescape/opa-utils/reporthandling/attacktrack/v1alpha1" + "k8s.io/utils/strings/slices" ) const ( supportBackwardCompatibility = true + TypeCompliance = "compliance" + TypeSecurity = "security" ) +// ============================================================= +// =========================== Rules =========================== +// ============================================================= + // GetOPAPolicies returns all the policies of given customer func (gs *GitRegoStore) GetOPAPolicies() ([]opapolicy.PolicyRule, error) { gs.rulesLock.RLock() @@ -61,6 +68,10 @@ func (gs *GitRegoStore) getOPAPolicyByName(ruleName string) (*opapolicy.PolicyRu return nil, fmt.Errorf("rule '%s' not found", ruleName) } +// ============================================================= +// =========================== AttackTracks ==================== +// ============================================================= + func (gs *GitRegoStore) GetAttackTracks() ([]v1alpha1.AttackTrack, error) { gs.attackTracksLock.RLock() defer gs.attackTracksLock.RUnlock() @@ -72,6 +83,10 @@ func (gs *GitRegoStore) GetAttackTracks() ([]v1alpha1.AttackTrack, error) { return gs.AttackTracks, nil } +// ============================================================= +// =========================== Controls ======================== +// ============================================================= + // GetOPAControlByName returns specific BaseControl by the name. // // Deprecated: use GetOPAControlByFrameworkNameAndControlName. @@ -257,40 +272,104 @@ func (gs *GitRegoStore) GetOpaFrameworkListByControlID(controlID string) []strin return frameworksNameList } -// GetOPAFrameworks returns all the frameworks of given customer -func (gs *GitRegoStore) GetOPAFrameworks() ([]opapolicy.Framework, error) { +// =============================================================== +// =========================== Frameworks ======================== +// =============================================================== + +// GetOPAFrameworksByType returns all frameworks of given type +func (gs *GitRegoStore) getOPAFrameworksByType(frameworkType string) ([]opapolicy.Framework, error) { gs.frameworksLock.RLock() defer gs.frameworksLock.RUnlock() if gs.Frameworks == nil { return nil, fmt.Errorf("no frameworks found in GitRegoStore") } - frameworksList := make([]opapolicy.Framework, 0, len(gs.Frameworks)) for _, frameworkToPin := range gs.Frameworks { + framework := frameworkToPin + if slices.Contains(framework.TypeTags, frameworkType) { + frameworksList = append(frameworksList, framework) + } + } + return frameworksList, nil +} + +// ====================== compliance frameworks ====================== + +// GetOPAFrameworks returns all compliance frameworks +func (gs *GitRegoStore) GetOPAFrameworks() ([]opapolicy.Framework, error) { + complianceFrameworks, err := gs.getOPAFrameworksByType(TypeCompliance) + if err != nil { + return nil, fmt.Errorf("failed to get compliance frameworks: %w", err) + } + + frameworksList := make([]opapolicy.Framework, 0, len(complianceFrameworks)) + for _, frameworkToPin := range complianceFrameworks { fw := frameworkToPin if err := gs.fillControlsAndControlIDsInFramework(&fw); err != nil { return nil, err } - frameworksList = append(frameworksList, fw) } return frameworksList, nil } +// GetOPAFrameworksNamesList returns all compliance frameworks names func (gs *GitRegoStore) GetOPAFrameworksNamesList() ([]string, error) { - gs.frameworksLock.RLock() - defer gs.frameworksLock.RUnlock() - - frameworksNameList := make([]string, 0, len(gs.Frameworks)) - for _, framework := range gs.Frameworks { + complianceFrameworks, err := gs.getOPAFrameworksByType(TypeCompliance) + if err != nil { + return nil, fmt.Errorf("failed to get compliance frameworks: %w", err) + } + frameworksNameList := make([]string, 0, len(complianceFrameworks)) + for _, framework := range complianceFrameworks { frameworksNameList = append(frameworksNameList, framework.Name) } return frameworksNameList, nil } +// ====================== security frameworks ====================== + +// GetOPAFrameworks returns all security frameworks +func (gs *GitRegoStore) GetOPASecurityFrameworks() ([]opapolicy.Framework, error) { + securityFrameworks, err := gs.getOPAFrameworksByType(TypeSecurity) + if err != nil { + return nil, fmt.Errorf("failed to get security frameworks: %w", err) + } + frameworksList := make([]opapolicy.Framework, 0, len(securityFrameworks)) + for _, frameworkToPin := range securityFrameworks { + fw := frameworkToPin + if err := gs.fillControlsAndControlIDsInFramework(&fw); err != nil { + return nil, err + } + frameworksList = append(frameworksList, fw) + } + return frameworksList, nil +} + +// GetOPAFrameworksNamesList returns all security frameworks names +func (gs *GitRegoStore) GetOPASecurityFrameworksNamesList() ([]string, error) { + securityFrameworks, err := gs.getOPAFrameworksByType(TypeSecurity) + if err != nil { + return nil, fmt.Errorf("failed to get security frameworks: %w", err) + } + frameworksNameList := make([]string, 0, len(securityFrameworks)) + for _, framework := range securityFrameworks { + frameworksNameList = append(frameworksNameList, framework.Name) + } + return frameworksNameList, nil +} + +// GetOPAFrameworkTypeTags returns all type tags of given framework +func (gs *GitRegoStore) GetOPAFrameworkTypeTags(frameworkName string) ([]string, error) { + framework, err := gs.getOPAFrameworkByName(frameworkName) + if err != nil { + return nil, err + } + return framework.TypeTags, nil +} + // GetOPAFrameworkByName returns specific framework by the name func (gs *GitRegoStore) GetOPAFrameworkByName(frameworkName string) (*opapolicy.Framework, error) { gs.frameworksLock.RLock() @@ -320,6 +399,8 @@ func (gs *GitRegoStore) getOPAFrameworkByName(frameworkName string) (*opapolicy. return nil, fmt.Errorf("framework '%s' not found", frameworkName) } +// =============================================================== + func (gs *GitRegoStore) GetDefaultConfigInputs() (armotypes.CustomerConfig, error) { gs.DefaultConfigInputsLock.RLock() defer gs.DefaultConfigInputsLock.RUnlock() @@ -334,6 +415,8 @@ func (gs *GitRegoStore) GetSystemPostureExceptionPolicies() ([]armotypes.Posture return gs.SystemPostureExceptionPolicies, nil } +// ====================== helpers ====================== + func (gs *GitRegoStore) fillRulesAndRulesIDsInControl(control *opapolicy.Control) error { gs.controlEscalatedLock.Lock() // this locks all concurrent attempts to fill any control defer gs.controlEscalatedLock.Unlock() diff --git a/gitregostore/gitstoremethods_test.go b/gitregostore/gitstoremethods_test.go index 6a834b323..3c2374bed 100644 --- a/gitregostore/gitstoremethods_test.go +++ b/gitregostore/gitstoremethods_test.go @@ -4,6 +4,8 @@ import ( "strings" "testing" + "github.com/armosec/armoapi-go/armotypes" + opapolicy "github.com/kubescape/opa-utils/reporthandling" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -196,3 +198,81 @@ func TestGetPoliciesMethodsDevNew(t *testing.T) { gs_tests(t, gs) } + +// Create a mock GitRegoStore instance +var gitRegoStoreMock = &GitRegoStore{ + Frameworks: []opapolicy.Framework{ + { + PortalBase: armotypes.PortalBase{Name: "MITRE"}, + TypeTags: []string{"compliance"}, + }, + { + PortalBase: armotypes.PortalBase{Name: "NSA"}, + TypeTags: []string{"compliance"}, + }, + { + PortalBase: armotypes.PortalBase{Name: "security"}, + TypeTags: []string{"security"}, + }, + }} + +func TestGetOPAFrameworksByType(t *testing.T) { + gs := gitRegoStoreMock + complianceFrameworks, err := gs.getOPAFrameworksByType("compliance") + assert.NoError(t, err) + assert.NotEmptyf(t, complianceFrameworks, "failed to get all frameworks %v", err) + assert.Equal(t, 2, len(complianceFrameworks)) + + securityFrameworks, err := gs.getOPAFrameworksByType("security") + assert.NoError(t, err) + assert.NotEmptyf(t, securityFrameworks, "failed to get all frameworks %v", err) + assert.Equal(t, 1, len(securityFrameworks)) +} + +func TestGetOPAFrameworks(t *testing.T) { + gs := gitRegoStoreMock + frameworks, err := gs.GetOPAFrameworks() + assert.NoError(t, err) + assert.NotEmptyf(t, frameworks, "failed to get all frameworks %v", err) + assert.Equal(t, 2, len(frameworks)) +} + +func TestGetOPAFrameworksNamesList(t *testing.T) { + gs := gitRegoStoreMock + frameworksNames, err := gs.GetOPAFrameworksNamesList() + assert.NoError(t, err) + assert.NotEmptyf(t, frameworksNames, "failed to get all frameworks %v", err) + assert.Equal(t, 2, len(frameworksNames)) + assert.Contains(t, frameworksNames, "MITRE") + assert.Contains(t, frameworksNames, "NSA") +} + +func TestGetOPASecurityFrameworks(t *testing.T) { + gs := gitRegoStoreMock + securityFrameworks, err := gs.GetOPASecurityFrameworks() + assert.NoError(t, err) + assert.NotEmptyf(t, securityFrameworks, "failed to get all frameworks %v", err) + assert.Equal(t, 1, len(securityFrameworks)) +} + +func TestGetOPASecurityFrameworksNamesList(t *testing.T) { + gs := gitRegoStoreMock + securityFrameworks, err := gs.GetOPASecurityFrameworksNamesList() + assert.NoError(t, err) + assert.NotEmptyf(t, securityFrameworks, "failed to get all frameworks %v", err) + assert.Equal(t, 1, len(securityFrameworks)) + assert.Contains(t, securityFrameworks, "security") +} + +func TestGetOPAFrameworkTypeTags(t *testing.T) { + gs := gitRegoStoreMock + nsaTypeTags, err := gs.GetOPAFrameworkTypeTags("NSA") + assert.NoError(t, err) + assert.Equal(t, 1, len(nsaTypeTags)) + assert.Contains(t, nsaTypeTags, "compliance") + + securityTypeTags, err := gs.GetOPAFrameworkTypeTags("security") + assert.NoError(t, err) + assert.Equal(t, 1, len(securityTypeTags)) + assert.Contains(t, securityTypeTags, "security") +} diff --git a/gitregostore/gitstoreutils.go b/gitregostore/gitstoreutils.go index 14c4cc7cb..947630e6d 100644 --- a/gitregostore/gitstoreutils.go +++ b/gitregostore/gitstoreutils.go @@ -24,6 +24,7 @@ const ( attackTracksJsonFileName = "attack_tracks.json" attackTracksPathPrefix = "attack-tracks" frameworksJsonFileName = "frameworks.json" + securityFrameworksJsonFileName = "security_frameworks.json" controlsJsonFileName = "controls.json" rulesJsonFileName = "rules.json" frameworkControlRelationsFileName = "FWName_CID_CName.csv" @@ -297,10 +298,18 @@ func (gs *GitRegoStore) setFrameworks(respStr string) error { if err := JSONDecoder(respStr).Decode(&frameworks); err != nil { return err } + respStr1, err := HttpGetter(gs.httpClient, fmt.Sprintf("%s/%s", gs.URL, gs.stripExtention(securityFrameworksJsonFileName))) + if err != nil { + return fmt.Errorf("error getting: %s from: '%s' ,error: %s", securityFrameworksJsonFileName, gs.URL, err) + } + securityFrameworks := []opapolicy.Framework{} + if err := JSONDecoder(respStr1).Decode(&securityFrameworks); err != nil { + return err + } gs.frameworksLock.Lock() defer gs.frameworksLock.Unlock() - gs.Frameworks = frameworks + gs.Frameworks = append(frameworks, securityFrameworks...) return nil } From ecd8c67a6920b8feb9f7b8e6f64348a64cd33d0c Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Tue, 20 Jun 2023 14:31:24 +0300 Subject: [PATCH 02/48] update opautils version Signed-off-by: YiscahLevySilas1 --- go.mod | 34 ++++++++++++++++--------------- go.sum | 63 +++++++++++++++++++++++++++++++--------------------------- 2 files changed, 52 insertions(+), 45 deletions(-) diff --git a/go.mod b/go.mod index a1f0a8d02..c3ec39e79 100644 --- a/go.mod +++ b/go.mod @@ -4,11 +4,12 @@ go 1.19 require ( github.com/alecthomas/assert/v2 v2.2.1 - github.com/armosec/armoapi-go v0.0.119 + github.com/armosec/armoapi-go v0.0.173 github.com/go-gota/gota v0.12.0 - github.com/kubescape/opa-utils v0.0.223 - github.com/stretchr/testify v1.8.0 + github.com/kubescape/opa-utils v0.0.250-0.20230620072457-33bbba804d75 + github.com/stretchr/testify v1.8.3 go.uber.org/zap v1.24.0 + k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed ) require ( @@ -27,36 +28,36 @@ require ( github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 // indirect github.com/OneOfOne/xxhash v1.2.8 // indirect - github.com/PuerkitoBio/purell v1.1.1 // indirect - github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/agnivade/levenshtein v1.1.1 // indirect github.com/alecthomas/repr v0.2.0 // indirect github.com/armosec/utils-go v0.0.12 // indirect github.com/armosec/utils-k8s-go v0.0.12 // indirect - github.com/aws/aws-sdk-go-v2 v1.16.7 // indirect + github.com/aws/aws-sdk-go-v2 v1.17.3 // indirect github.com/aws/aws-sdk-go-v2/config v1.15.13 // indirect github.com/aws/aws-sdk-go-v2/credentials v1.12.8 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.8 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.14 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.8 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.27 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.21 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.3.15 // indirect + github.com/aws/aws-sdk-go-v2/service/ecr v1.18.0 // indirect github.com/aws/aws-sdk-go-v2/service/eks v1.21.4 // indirect + github.com/aws/aws-sdk-go-v2/service/iam v1.19.0 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.8 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.11.11 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.16.9 // indirect - github.com/aws/smithy-go v1.12.0 // indirect + github.com/aws/smithy-go v1.13.5 // 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.24+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/emicklei/go-restful/v3 v3.9.0 // 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-logr/logr v1.2.3 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.20.0 // indirect github.com/go-openapi/swag v0.19.14 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect @@ -64,7 +65,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect - github.com/google/go-cmp v0.5.8 // indirect + github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/uuid v1.3.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa // indirect @@ -75,7 +76,7 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kubescape/go-logger v0.0.6 // indirect - github.com/kubescape/k8s-interface v0.0.93 // indirect + github.com/kubescape/k8s-interface v0.0.99 // indirect github.com/kubescape/rbac-utils v0.0.20 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/mailru/easyjson v0.7.6 // indirect @@ -94,6 +95,7 @@ require ( github.com/pquerna/cachecontrol v0.1.0 // indirect github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/stripe/stripe-go/v74 v74.8.0 // indirect github.com/tchap/go-patricia/v2 v2.3.1 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect @@ -102,6 +104,7 @@ require ( go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect + golang.org/x/exp v0.0.0-20230519143937-03e91628a987 // indirect golang.org/x/net v0.7.0 // indirect golang.org/x/oauth2 v0.0.0-20220630143837-2104d58473e0 // indirect golang.org/x/sys v0.5.0 // indirect @@ -121,9 +124,8 @@ require ( k8s.io/api v0.25.3 // indirect k8s.io/apimachinery v0.25.3 // indirect k8s.io/client-go v0.25.3 // indirect - k8s.io/klog/v2 v2.70.1 // indirect - k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect - k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect + k8s.io/klog/v2 v2.80.1 // indirect + k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect sigs.k8s.io/controller-runtime v0.12.3 // indirect sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect diff --git a/go.sum b/go.sum index ff178782f..46b6e63d4 100644 --- a/go.sum +++ b/go.sum @@ -99,10 +99,6 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8= github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= -github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8= github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= @@ -115,36 +111,44 @@ github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYU github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= -github.com/armosec/armoapi-go v0.0.119 h1:7XbvBbOKp26Bpp72LQ8Spw4FBpbXu3+qZFQyPEwTPFk= -github.com/armosec/armoapi-go v0.0.119/go.mod h1:2zoNzb3Fy9ZByeczJZ47ftDRLRzTykVdTISS3GTc/JU= +github.com/armosec/armoapi-go v0.0.173 h1:TwNxmTxx9ATJPZBlld/53s/WvSVUfoF4gxgHT6UbFng= +github.com/armosec/armoapi-go v0.0.173/go.mod h1:xlW8dGq0vVzbuk+kDZqMQIkfU9P/iiiiDavoCIboqgI= github.com/armosec/utils-go v0.0.12 h1:NXkG/BhbSVAmTVXr0qqsK02CmxEiXuJyPmdTRcZ4jAo= github.com/armosec/utils-go v0.0.12/go.mod h1:F/K1mI/qcj7fNuJl7xktoCeHM83azOF0Zq6eC2WuPyU= github.com/armosec/utils-k8s-go v0.0.12 h1:u7kHSUp4PpvPP3hEaRXMbM0Vw23IyLhAzzE+2TW6Jkk= github.com/armosec/utils-k8s-go v0.0.12/go.mod h1:rPHiOaHefWa9ujspwvYYAp0uEbqGGyAMiNrFa/Gpp/8= -github.com/aws/aws-sdk-go-v2 v1.16.7 h1:zfBwXus3u14OszRxGcqCDS4MfMCv10e8SMJ2r8Xm0Ns= github.com/aws/aws-sdk-go-v2 v1.16.7/go.mod h1:6CpKuLXg2w7If3ABZCl/qZ6rEgwtjZTn4eAf4RcEyuw= +github.com/aws/aws-sdk-go-v2 v1.17.3 h1:shN7NlnVzvDUgPQ+1rLMSxY8OWRNDRYtiqe0p/PgrhY= +github.com/aws/aws-sdk-go-v2 v1.17.3/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= github.com/aws/aws-sdk-go-v2/config v1.15.13 h1:CJH9zn/Enst7lDiGpoguVt0lZr5HcpNVlRJWbJ6qreo= github.com/aws/aws-sdk-go-v2/config v1.15.13/go.mod h1:AcMu50uhV6wMBUlURnEXhr9b3fX6FLSTlEV89krTEGk= github.com/aws/aws-sdk-go-v2/credentials v1.12.8 h1:niTa7zc7uyOP2ufri0jPESBt1h9yP3Zc0q+xzih3h8o= github.com/aws/aws-sdk-go-v2/credentials v1.12.8/go.mod h1:P2Hd4Sy7mXRxPNcQMPBmqszSJoDXexX8XEDaT6lucO0= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.8 h1:VfBdn2AxwMbFyJN/lF/xuT3SakomJ86PZu3rCxb5K0s= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.8/go.mod h1:oL1Q3KuCq1D4NykQnIvtRiBGLUXhcpY5pl6QZB2XEPU= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.14 h1:2C0pYHcUBmdzPj+EKNC4qj97oK6yjrUhc1KoSodglvk= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.14/go.mod h1:kdjrMwHwrC3+FsKhNcCMJ7tUVj/8uSD5CZXeQ4wV6fM= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.8 h1:2J+jdlBJWEmTyAwC82Ym68xCykIvnSnIN18b8xHGlcc= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.27 h1:I3cakv2Uy1vNmmhRQmFptYDxOvBnwCdNwyw63N0RaRU= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.27/go.mod h1:a1/UpzeyBBerajpnP5nGZa9mGzsBn5cOKxm6NWQsvoI= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.8/go.mod h1:ZIV8GYoC6WLBW5KGs+o4rsc65/ozd+eQ0L31XF5VDwk= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.21 h1:5NbbMrIzmUn/TXFqAle6mgrH5m9cOvMLRGL7pnG8tRE= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.21/go.mod h1:+Gxn8jYn5k9ebfHEqlhrMirFjSW0v0C9fI+KN5vk2kE= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.15 h1:QquxR7NH3ULBsKC+NoTpilzbKKS+5AELfNREInbhvas= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.15/go.mod h1:Tkrthp/0sNBShQQsamR7j/zY4p19tVTAs+nnqhH6R3c= +github.com/aws/aws-sdk-go-v2/service/ecr v1.18.0 h1:5RVanD+P+L2W9WU07/8J/A52vnQi7F3ClBdWQttgYlg= +github.com/aws/aws-sdk-go-v2/service/ecr v1.18.0/go.mod h1:9yGOFsa2OcdyePojE89xNGtdBusTyc8ocjpiuFtFc0g= github.com/aws/aws-sdk-go-v2/service/eks v1.21.4 h1:qmKWieiIiYwD46GRD6nxFc1KsyR0ChGRid8emb7rDEY= github.com/aws/aws-sdk-go-v2/service/eks v1.21.4/go.mod h1:Th2+t6mwi0bZayXUOFOTuyWR2nwRUVcadDy4WGE8C2E= +github.com/aws/aws-sdk-go-v2/service/iam v1.19.0 h1:9vCynoqC+dgxZKrsjvAniyIopsv3RZFsZ6wkQ+yxtj8= +github.com/aws/aws-sdk-go-v2/service/iam v1.19.0/go.mod h1:OyAuvpFeSVNppcSsp1hFOVQcaTRc1LE24YIR7pMbbAA= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.8 h1:oKnAXxSF2FUvfgw8uzU/v9OTYorJJZ8eBmWhr9TWVVQ= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.8/go.mod h1:rDVhIMAX9N2r8nWxDUlbubvvaFMnfsm+3jAV7q+rpM4= github.com/aws/aws-sdk-go-v2/service/sso v1.11.11 h1:XOJWXNFXJyapJqQuCIPfftsOf0XZZioM0kK6OPRt9MY= github.com/aws/aws-sdk-go-v2/service/sso v1.11.11/go.mod h1:MO4qguFjs3wPGcCSpQ7kOFTwRvb+eu+fn+1vKleGHUk= github.com/aws/aws-sdk-go-v2/service/sts v1.16.9 h1:yOfILxyjmtr2ubRkRJldlHDFBhf5vw4CzhbwWIBmimQ= github.com/aws/aws-sdk-go-v2/service/sts v1.16.9/go.mod h1:O1IvkYxr+39hRf960Us6j0x1P8pDqhTX+oXM5kQNl/Y= -github.com/aws/smithy-go v1.12.0 h1:gXpeZel/jPoWQ7OEmLIgCUnhkFftqNfwWUwAHSlp1v0= github.com/aws/smithy-go v1.12.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= +github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8= +github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -191,8 +195,8 @@ github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw= -github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= +github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -237,8 +241,8 @@ github.com/go-logr/zapr v1.2.0 h1:n4JnPI1T3Qq1SFEi/F8rwLrZERp2bso19PJZDB9dayk= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM= -github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= +github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= +github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= @@ -307,8 +311,9 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -388,10 +393,10 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kubescape/go-logger v0.0.6 h1:ynhAmwrz0O7Jtqq1CdmCZUrKveji25hVP+B/FAb3QrA= github.com/kubescape/go-logger v0.0.6/go.mod h1:DnVWEvC90LFY1nNMaNo6nBVOcqkLMK3S0qzXP1fzRvI= -github.com/kubescape/k8s-interface v0.0.93 h1:LC8SoQJ0nKVTXnNFjCMuVCafbojnjUvkEZ97c8Lo1eY= -github.com/kubescape/k8s-interface v0.0.93/go.mod h1:zhK3/8+ZVBpQHdILQnC4zddbx/YXMljffxZc2Kqkvoo= -github.com/kubescape/opa-utils v0.0.223 h1:t39+P5eW1nsmt55Sx7NZU3Tv9IDBo0ljEYbOi9nlgVc= -github.com/kubescape/opa-utils v0.0.223/go.mod h1:cKWsKl2t2XP7Mc3t1c3hNdf8Kg0sxikUcqATfq09vzU= +github.com/kubescape/k8s-interface v0.0.99 h1:Bk7P694WkYPORW4c+ojpvCIQQ83Ku8durElNlvgM0Qg= +github.com/kubescape/k8s-interface v0.0.99/go.mod h1:UO8puAwFZ3XVMlKWJj0GcdFJZI22Q7iwV+5FO6mw5FE= +github.com/kubescape/opa-utils v0.0.250-0.20230620072457-33bbba804d75 h1:ptOLb4/UM26xxpRGB+NST9EaFt7mIJh1TgGPZdFlEnw= +github.com/kubescape/opa-utils v0.0.250-0.20230620072457-33bbba804d75/go.mod h1:SkNqbhUGipSYVE+oAUaHko6aggp8XVVbDChoNg48lao= github.com/kubescape/rbac-utils v0.0.20 h1:1MMxsCsCZ3ntDi8f9ZYYcY+K7bv50bDW5ZvnGnhMhJw= github.com/kubescape/rbac-utils v0.0.20/go.mod h1:t57AhSrjuNGQ+mpZWQM/hBzrCOeKBDHegFoVo4tbikQ= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= @@ -494,16 +499,16 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stripe/stripe-go/v74 v74.8.0 h1:0+3EfQSBhMg8SQ1+w+AP6Gxyko2crWbUG2uXbzYs8SU= +github.com/stripe/stripe-go/v74 v74.8.0/go.mod h1:5PoXNp30AJ3tGq57ZcFuaMylzNi8KpwlrYAFmO1fHZw= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BGhTkes= github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k= @@ -563,8 +568,9 @@ golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20230519143937-03e91628a987 h1:3xJIFvzUFbu4ls0BTBYcgbCGhA63eAOEMxIHugyXJqA= +golang.org/x/exp v0.0.0-20230519143937-03e91628a987/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -614,7 +620,6 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1074,10 +1079,10 @@ k8s.io/apimachinery v0.25.3/go.mod h1:jaF9C/iPNM1FuLl7Zuy5b9v+n35HGSh6AQ4HYRkCqw k8s.io/client-go v0.25.3 h1:oB4Dyl8d6UbfDHD8Bv8evKylzs3BXzzufLiO27xuPs0= k8s.io/client-go v0.25.3/go.mod h1:t39LPczAIMwycjcXkVc+CB+PZV69jQuNx4um5ORDjQA= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.70.1 h1:7aaoSdahviPmR+XkS7FyxlkkXs6tHISSG03RxleQAVQ= -k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA= -k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU= +k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= +k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/lQhTmy+Hr/Cpue4= k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= From 9de25ecace1a91663a0871105980c325590d6305 Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Tue, 20 Jun 2023 14:54:10 +0300 Subject: [PATCH 03/48] update NewDevGitRegoStore Signed-off-by: YiscahLevySilas1 --- gitregostore/datastructures.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitregostore/datastructures.go b/gitregostore/datastructures.go index 660a31edc..7cd65964c 100644 --- a/gitregostore/datastructures.go +++ b/gitregostore/datastructures.go @@ -106,6 +106,6 @@ func NewDefaultGitRegoStore(frequency int) *GitRegoStore { // NewDevGitRegoStore - generates git store object for dev regolibrary release files // Release files source: "https://raw.githubusercontent.com/kubescape/regolibrary-dev/main/releaseDev" func NewDevGitRegoStore(frequency int) *GitRegoStore { - gs := NewGitRegoStore("https://raw.githubusercontent.com", "kubescape", "regolibrary-dev", "releaseDev", "", "main", frequency) + gs := NewGitRegoStore("https://raw.githubusercontent.com", "kubescape", "regolibrary-dev", "releaseDev", "/", "main", frequency) return gs } From 830ec0a3344ee44991b12bca486666ad16d858df Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Tue, 20 Jun 2023 14:55:53 +0300 Subject: [PATCH 04/48] temporarily disable test Signed-off-by: YiscahLevySilas1 --- gitregostore/gitstoremethods_test.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/gitregostore/gitstoremethods_test.go b/gitregostore/gitstoremethods_test.go index 3c2374bed..85c6a4849 100644 --- a/gitregostore/gitstoremethods_test.go +++ b/gitregostore/gitstoremethods_test.go @@ -158,17 +158,17 @@ func gs_tests(t *testing.T, gs *GitRegoStore) { }) } -func TestGetPoliciesMethodsNew(t *testing.T) { - t.Parallel() +// func TestGetPoliciesMethodsNew(t *testing.T) { +// t.Parallel() - gs := NewDefaultGitRegoStore(-1) - t.Run("shoud set objects in rego store", func(t *testing.T) { - require.NoError(t, gs.SetRegoObjects()) - }) +// gs := NewDefaultGitRegoStore(-1) +// t.Run("shoud set objects in rego store", func(t *testing.T) { +// require.NoError(t, gs.SetRegoObjects()) +// }) - gs_tests(t, gs) +// gs_tests(t, gs) -} +// } func TestGetOPAFrameworkByName(t *testing.T) { t.Parallel() From 4b7d96f2d56ff42fbce5764d91d4f23edd1a8fd1 Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Tue, 20 Jun 2023 16:44:05 +0300 Subject: [PATCH 05/48] enable test Signed-off-by: YiscahLevySilas1 --- gitregostore/gitstoremethods_test.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/gitregostore/gitstoremethods_test.go b/gitregostore/gitstoremethods_test.go index 85c6a4849..3c2374bed 100644 --- a/gitregostore/gitstoremethods_test.go +++ b/gitregostore/gitstoremethods_test.go @@ -158,17 +158,17 @@ func gs_tests(t *testing.T, gs *GitRegoStore) { }) } -// func TestGetPoliciesMethodsNew(t *testing.T) { -// t.Parallel() +func TestGetPoliciesMethodsNew(t *testing.T) { + t.Parallel() -// gs := NewDefaultGitRegoStore(-1) -// t.Run("shoud set objects in rego store", func(t *testing.T) { -// require.NoError(t, gs.SetRegoObjects()) -// }) + gs := NewDefaultGitRegoStore(-1) + t.Run("shoud set objects in rego store", func(t *testing.T) { + require.NoError(t, gs.SetRegoObjects()) + }) -// gs_tests(t, gs) + gs_tests(t, gs) -// } +} func TestGetOPAFrameworkByName(t *testing.T) { t.Parallel() From d5943784bec2d536f9e001f25781c75bf3d36d30 Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Wed, 21 Jun 2023 13:22:04 +0300 Subject: [PATCH 06/48] update opa-utils version Signed-off-by: YiscahLevySilas1 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c3ec39e79..5564d2f0d 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/alecthomas/assert/v2 v2.2.1 github.com/armosec/armoapi-go v0.0.173 github.com/go-gota/gota v0.12.0 - github.com/kubescape/opa-utils v0.0.250-0.20230620072457-33bbba804d75 + github.com/kubescape/opa-utils v0.0.250 github.com/stretchr/testify v1.8.3 go.uber.org/zap v1.24.0 k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed diff --git a/go.sum b/go.sum index 46b6e63d4..a0b392374 100644 --- a/go.sum +++ b/go.sum @@ -395,8 +395,8 @@ github.com/kubescape/go-logger v0.0.6 h1:ynhAmwrz0O7Jtqq1CdmCZUrKveji25hVP+B/FAb github.com/kubescape/go-logger v0.0.6/go.mod h1:DnVWEvC90LFY1nNMaNo6nBVOcqkLMK3S0qzXP1fzRvI= github.com/kubescape/k8s-interface v0.0.99 h1:Bk7P694WkYPORW4c+ojpvCIQQ83Ku8durElNlvgM0Qg= github.com/kubescape/k8s-interface v0.0.99/go.mod h1:UO8puAwFZ3XVMlKWJj0GcdFJZI22Q7iwV+5FO6mw5FE= -github.com/kubescape/opa-utils v0.0.250-0.20230620072457-33bbba804d75 h1:ptOLb4/UM26xxpRGB+NST9EaFt7mIJh1TgGPZdFlEnw= -github.com/kubescape/opa-utils v0.0.250-0.20230620072457-33bbba804d75/go.mod h1:SkNqbhUGipSYVE+oAUaHko6aggp8XVVbDChoNg48lao= +github.com/kubescape/opa-utils v0.0.250 h1:SpMjtDB3EgyvbwxpCpZXAtQ/TixOeVQAmkcfi+w66KA= +github.com/kubescape/opa-utils v0.0.250/go.mod h1:SkNqbhUGipSYVE+oAUaHko6aggp8XVVbDChoNg48lao= github.com/kubescape/rbac-utils v0.0.20 h1:1MMxsCsCZ3ntDi8f9ZYYcY+K7bv50bDW5ZvnGnhMhJw= github.com/kubescape/rbac-utils v0.0.20/go.mod h1:t57AhSrjuNGQ+mpZWQM/hBzrCOeKBDHegFoVo4tbikQ= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= From a176143f02936a30995c6b9d6ed114b950d3c682 Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Wed, 21 Jun 2023 13:58:40 +0300 Subject: [PATCH 07/48] add 2 new attack-tracks Signed-off-by: YiscahLevySilas1 --- attack-tracks/service-destruction.json | 18 ++++++++++ attack-tracks/workload-external-track.json | 38 ++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 attack-tracks/service-destruction.json create mode 100644 attack-tracks/workload-external-track.json diff --git a/attack-tracks/service-destruction.json b/attack-tracks/service-destruction.json new file mode 100644 index 000000000..75aa03c43 --- /dev/null +++ b/attack-tracks/service-destruction.json @@ -0,0 +1,18 @@ +{ + "apiVersion": "regolibrary.kubescape/v1alpha1", + "kind": "AttackTrack", + "metadata": { + "name": "workload-external-track" + }, + "spec": { + "version": "1.0", + "data": { + "name": "Workload Exposure", + "subSteps": [ + { + "name": "Service Destruction" + } + ] + } + } +} \ No newline at end of file diff --git a/attack-tracks/workload-external-track.json b/attack-tracks/workload-external-track.json new file mode 100644 index 000000000..2018ce2f1 --- /dev/null +++ b/attack-tracks/workload-external-track.json @@ -0,0 +1,38 @@ +{ + "apiVersion": "regolibrary.kubescape/v1alpha1", + "kind": "AttackTrack", + "metadata": { + "name": "workload-external-track" + }, + "spec": { + "version": "1.0", + "data": { + "name": "Workload Exposure", + "subSteps": [ + { + "name": "Vulnerable Image", + "subSteps": [ + { + "name": "Data Access" + }, + { + "name": "Secret Access" + }, + { + "name": "Credential access" + }, + { + "name": "Potential Node exposure" + }, + { + "name": "Persistence" + }, + { + "name": "Network" + } + ] + } + ] + } + } +} \ No newline at end of file From a43de1ebd4e0cafd92ce69448ae4623367c720e2 Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Wed, 21 Jun 2023 14:04:37 +0300 Subject: [PATCH 08/48] fix name Signed-off-by: YiscahLevySilas1 --- attack-tracks/service-destruction.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/attack-tracks/service-destruction.json b/attack-tracks/service-destruction.json index 75aa03c43..745b81164 100644 --- a/attack-tracks/service-destruction.json +++ b/attack-tracks/service-destruction.json @@ -2,7 +2,7 @@ "apiVersion": "regolibrary.kubescape/v1alpha1", "kind": "AttackTrack", "metadata": { - "name": "workload-external-track" + "name": "service-destruction" }, "spec": { "version": "1.0", From df461930e36ae969c717ae78ec5363343b22528c Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Wed, 21 Jun 2023 15:49:09 +0300 Subject: [PATCH 09/48] add new control jsons Signed-off-by: YiscahLevySilas1 --- controls/C-0255-workloadwithsecretaccess.json | 23 +++++++++++++++ controls/C-0256-exposuretointernet.json | 29 +++++++++++++++++++ controls/C-0257-pvcaccess.json | 23 +++++++++++++++ controls/C-0258-configmapaccess.json | 23 +++++++++++++++ .../C-0259-workloadwithcredentialaccess.json | 23 +++++++++++++++ controls/C-0260-missingnetworkpolicy.json | 23 +++++++++++++++ controls/C-0261-satokenmounted.json | 23 +++++++++++++++ 7 files changed, 167 insertions(+) create mode 100644 controls/C-0255-workloadwithsecretaccess.json create mode 100644 controls/C-0256-exposuretointernet.json create mode 100644 controls/C-0257-pvcaccess.json create mode 100644 controls/C-0258-configmapaccess.json create mode 100644 controls/C-0259-workloadwithcredentialaccess.json create mode 100644 controls/C-0260-missingnetworkpolicy.json create mode 100644 controls/C-0261-satokenmounted.json diff --git a/controls/C-0255-workloadwithsecretaccess.json b/controls/C-0255-workloadwithsecretaccess.json new file mode 100644 index 000000000..c18655045 --- /dev/null +++ b/controls/C-0255-workloadwithsecretaccess.json @@ -0,0 +1,23 @@ +{ + "name": "Workload with secret access", + "attributes": { + "armoBuiltin": true, + "controlTypeTags": [ + "security" + ], + "attackTracks": [ + { + "attackTrack": "workload-external-track", + "categories": [ + "Secret Access" + ] + } + ] + }, + "description": "", + "remediation": "", + "rulesNames": [], + "test": "", + "controlID": "C-0255", + "baseScore": 4.0 +} \ No newline at end of file diff --git a/controls/C-0256-exposuretointernet.json b/controls/C-0256-exposuretointernet.json new file mode 100644 index 000000000..4f9e34571 --- /dev/null +++ b/controls/C-0256-exposuretointernet.json @@ -0,0 +1,29 @@ +{ + "name": "Exposure to internet", + "attributes": { + "armoBuiltin": true, + "controlTypeTags": [ + "security" + ], + "attackTracks": [ + { + "attackTrack": "workload-external-track", + "categories": [ + "Workload Exposure" + ] + }, + { + "attackTrack": "", + "categories": [ + "" + ] + } + ] + }, + "description": "", + "remediation": "", + "rulesNames": [], + "test": "", + "controlID": "C-0256", + "baseScore": 6.0 +} \ No newline at end of file diff --git a/controls/C-0257-pvcaccess.json b/controls/C-0257-pvcaccess.json new file mode 100644 index 000000000..99a0bac53 --- /dev/null +++ b/controls/C-0257-pvcaccess.json @@ -0,0 +1,23 @@ +{ + "name": "PVC access", + "attributes": { + "armoBuiltin": true, + "controlTypeTags": [ + "security" + ], + "attackTracks": [ + { + "attackTrack": "workload-external-track", + "categories": [ + "Data Access" + ] + } + ] + }, + "description": "", + "remediation": "", + "rulesNames": [], + "test": "", + "controlID": "C-0257", + "baseScore": 4.0 +} \ No newline at end of file diff --git a/controls/C-0258-configmapaccess.json b/controls/C-0258-configmapaccess.json new file mode 100644 index 000000000..4c857b17f --- /dev/null +++ b/controls/C-0258-configmapaccess.json @@ -0,0 +1,23 @@ +{ + "name": "ConfigMap access", + "attributes": { + "armoBuiltin": true, + "controlTypeTags": [ + "security" + ], + "attackTracks": [ + { + "attackTrack": "workload-external-track", + "categories": [ + "Data Access" + ] + } + ] + }, + "description": "", + "remediation": "", + "rulesNames": [], + "test": "", + "controlID": "C-0258", + "baseScore": 4.0 +} \ No newline at end of file diff --git a/controls/C-0259-workloadwithcredentialaccess.json b/controls/C-0259-workloadwithcredentialaccess.json new file mode 100644 index 000000000..eca60a6d5 --- /dev/null +++ b/controls/C-0259-workloadwithcredentialaccess.json @@ -0,0 +1,23 @@ +{ + "name": "Workload with credential access", + "attributes": { + "armoBuiltin": true, + "controlTypeTags": [ + "security" + ], + "attackTracks": [ + { + "attackTrack": "workload-external-track", + "categories": [ + "Credential access" + ] + } + ] + }, + "description": "", + "remediation": "", + "rulesNames": [], + "test": "", + "controlID": "C-0259", + "baseScore": 8.0 +} \ No newline at end of file diff --git a/controls/C-0260-missingnetworkpolicy.json b/controls/C-0260-missingnetworkpolicy.json new file mode 100644 index 000000000..08af08bc3 --- /dev/null +++ b/controls/C-0260-missingnetworkpolicy.json @@ -0,0 +1,23 @@ +{ + "name": "Missing network policy", + "attributes": { + "armoBuiltin": true, + "controlTypeTags": [ + "security" + ], + "attackTracks": [ + { + "attackTrack": "workload-external-track", + "categories": [ + "Network" + ] + } + ] + }, + "description": "", + "remediation": "", + "rulesNames": [], + "test": "", + "controlID": "C-0260", + "baseScore": 4.0 +} \ No newline at end of file diff --git a/controls/C-0261-satokenmounted.json b/controls/C-0261-satokenmounted.json new file mode 100644 index 000000000..aa7f667c7 --- /dev/null +++ b/controls/C-0261-satokenmounted.json @@ -0,0 +1,23 @@ +{ + "name": "SA token mounted", + "attributes": { + "armoBuiltin": true, + "controlTypeTags": [ + "security" + ], + "attackTracks": [ + { + "attackTrack": "workload-external-track", + "categories": [ + "Credential access" + ] + } + ] + }, + "description": "", + "remediation": "", + "rulesNames": [], + "test": "", + "controlID": "C-0261", + "baseScore": 6.0 +} \ No newline at end of file From 699b220dedf57dabc3faa1da87965d29db91e5c9 Mon Sep 17 00:00:00 2001 From: kooomix Date: Thu, 22 Jun 2023 08:35:56 +0300 Subject: [PATCH 10/48] improved tests --- gitregostore/gitstoremethods_test.go | 54 +++++++ gitregostore/gitstoreutils.go | 208 +-------------------------- gitregostore/gitstoreutils_test.go | 26 ++-- 3 files changed, 66 insertions(+), 222 deletions(-) diff --git a/gitregostore/gitstoremethods_test.go b/gitregostore/gitstoremethods_test.go index 3c2374bed..a04151525 100644 --- a/gitregostore/gitstoremethods_test.go +++ b/gitregostore/gitstoremethods_test.go @@ -13,6 +13,44 @@ import ( func gs_tests(t *testing.T, gs *GitRegoStore) { index := 0 + t.Run("should retrieve DefaultConfigInput", func(t *testing.T) { + t.Parallel() + + customerConfig, err := gs.GetDefaultConfigInputs() + assert.NoError(t, err) + assert.NotEmpty(t, customerConfig, "failed to get config inputs %v", err) + }) + + t.Run("should retrieve AttackTracks", func(t *testing.T) { + t.Parallel() + + systemPostureExceptionPolicies, err := gs.GetSystemPostureExceptionPolicies() + assert.NoError(t, err) + assert.NotEmpty(t, systemPostureExceptionPolicies, "failed to get SystemPostureExceptionPolicies %v", err) + }) + + t.Run("should retrieve AttackTracks", func(t *testing.T) { + t.Parallel() + + attachTrack, err := gs.GetAttackTracks() + assert.NoError(t, err) + assert.NotEmpty(t, attachTrack, "failed to get attack tracks %v", err) + }) + + t.Run("should retrieve framework by name", func(t *testing.T) { + t.Parallel() + + frameworks := gs.GetOpaFrameworkListByControlID("C-0016") + assert.NotEmpty(t, frameworks, "failed to get framework by control ID 'C-0016' %v", frameworks) + }) + + t.Run("should retrieve framework by name", func(t *testing.T) { + t.Parallel() + + frameworks := gs.GetOpaFrameworkListByControlName("Allow privilege escalation") + assert.NotEmpty(t, frameworks, "failed to get framework by control name 'Allow privilege escalation' %v", frameworks) + }) + t.Run("should retrieve OPA rules (policies)", func(t *testing.T) { t.Parallel() @@ -55,6 +93,22 @@ func gs_tests(t *testing.T, gs *GitRegoStore) { ) }) + t.Run("should retrieve OPA control by id or name", func(t *testing.T) { + t.Parallel() + + controls, err := gs.GetOPAControl("C-0016") + assert.NoError(t, err) + assert.NotEmptyf(t, controls, + "failed to get control 'C-0016' %v", err, + ) + + controls, err = gs.GetOPAControl("Allow privilege escalation") + assert.NoError(t, err) + assert.NotEmptyf(t, controls, + "failed to get control 'Allow privilege escalation' %v", err, + ) + }) + t.Run("should retrieve OPA controls names", func(t *testing.T) { t.Parallel() diff --git a/gitregostore/gitstoreutils.go b/gitregostore/gitstoreutils.go index 947630e6d..eefc1cdf7 100644 --- a/gitregostore/gitstoreutils.go +++ b/gitregostore/gitstoreutils.go @@ -72,110 +72,6 @@ func (gs *GitRegoStore) setURL() { } } -func (gs *GitRegoStore) setObjects() error { - // This condition to support old reading files from repo. - // Once dev helm parameters are updated to new releaseDev folder, this condition should be removed. - if gs.Path == "git/trees" { - return gs.setObjectsFromRepoOnce() - } - return gs.setObjectsFromReleaseLoop() -} - -// DEPRECATED -func (gs *GitRegoStore) setObjectsFromRepoOnce() error { - - url := gs.BaseUrl + "/" + gs.Owner + "/" + gs.Repository + "/" + gs.Path + "/" + gs.Branch + "?recursive=1" - - body, err := HttpGetter(gs.httpClient, url) - if err != nil { - return err - } - var trees Tree - err = json.Unmarshal([]byte(body), &trees) - if err != nil { - return fmt.Errorf("failed to unmarshal response body from '%s', reason: %s", gs.URL, err.Error()) - } - - //use a clone of the store for the update to avoid long lock time - gsClone := newGitRegoStore(gs.BaseUrl, gs.Owner, gs.Repository, gs.Path, gs.Tag, gs.Branch, gs.FrequencyPullFromGitMinutes) - - // use only json files from relevant dirs - for _, path := range trees.TREE { - rawDataPath := "https://raw.githubusercontent.com/" + gsClone.Owner + "/" + gsClone.Repository + "/" + gsClone.Branch + "/" + path.PATH - - if strings.HasPrefix(path.PATH, strings.Replace(rulesJsonFileName, ".json", "/", -1)) && strings.HasSuffix(path.PATH, ".json") && !strings.Contains(path.PATH, "/test/") { - respStr, err := HttpGetter(gsClone.httpClient, rawDataPath) - if err != nil { - return err - } - if err := gsClone.setRulesWithRawRego(respStr, rawDataPath); err != nil { - zap.L().Debug("In setObjectsFromRepoOnce - failed to set rule %s\n", zap.String("path", rawDataPath)) - return err - } - } else if strings.HasPrefix(path.PATH, strings.Replace(controlsJsonFileName, ".json", "/", -1)) && strings.HasSuffix(path.PATH, ".json") { - respStr, err := HttpGetter(gs.httpClient, rawDataPath) - if err != nil { - return err - } - if err := gsClone.setControl(respStr); err != nil { - zap.L().Debug("In setObjectsFromRepoOnce - failed to set control %s\n", zap.String("path", rawDataPath)) - return err - } - } else if strings.HasPrefix(path.PATH, strings.Replace(frameworksJsonFileName, ".json", "/", -1)) && strings.HasSuffix(path.PATH, ".json") { - respStr, err := HttpGetter(gs.httpClient, rawDataPath) - if err != nil { - return err - } - if err := gsClone.setFramework(respStr); err != nil { - zap.L().Debug("In setObjectsFromRepoOnce - failed to set framework %s\n", zap.String("path", rawDataPath)) - return err - } - } else if strings.HasPrefix(path.PATH, attackTracksPathPrefix+"/") && strings.HasSuffix(path.PATH, ".json") { - respStr, err := HttpGetter(gs.httpClient, rawDataPath) - if err != nil { - return nil - } - if err := gsClone.setAttackTrack(respStr); err != nil { - zap.L().Debug("In setObjectsFromRepoOnce - failed to set attack track %s\n", zap.String("path", rawDataPath)) - return nil - } - } else if strings.HasPrefix(path.PATH, defaultConfigInputsFileName) && strings.HasSuffix(path.PATH, ".json") { - respStr, err := HttpGetter(gs.httpClient, rawDataPath) - if err != nil { - return err - } - if err := gsClone.setDefaultConfigInputs(respStr); err != nil { - zap.L().Debug("In setObjectsFromRepoOnce - failed to set DefaultConfigInputs %s\n", zap.String("path", rawDataPath)) - return err - } - } else if strings.HasPrefix(path.PATH, systemPostureExceptionFileName+"/") && strings.HasSuffix(path.PATH, ".json") { - respStr, err := HttpGetter(gs.httpClient, rawDataPath) - if err != nil { - return err - } - if err := gsClone.setSystemPostureExceptionPolicy(respStr); err != nil { - zap.L().Debug("In setObjectsFromRepoOnce - failed to set setSystemPostureExceptionPolicy %s\n", zap.String("path", rawDataPath)) - return err - } - } else if strings.HasSuffix(path.PATH, ControlRuleRelationsFileName) { - respStr, err := HttpGetter(gs.httpClient, rawDataPath) - if err != nil { - return err - } - gsClone.setControlRuleRelations(respStr) - } else if strings.HasSuffix(path.PATH, frameworkControlRelationsFileName) { - respStr, err := HttpGetter(gs.httpClient, rawDataPath) - if err != nil { - return err - } - gsClone.setFrameworkControlRelations(respStr) - } - } - - gs.copyData(gsClone) - return nil -} - func (gs *GitRegoStore) setFramework(respStr string) error { framework := &opapolicy.Framework{} if err := JSONDecoder(respStr).Decode(framework); err != nil { @@ -213,49 +109,9 @@ func (gs *GitRegoStore) setControl(respStr string) error { return nil } -func (gs *GitRegoStore) setRulesWithRawRego(respStr string, path string) error { - rule := &opapolicy.PolicyRule{} - rawRego, err := gs.getRulesWithRawRego(rule, respStr, path) - if err != nil { - return err - } - filterRego, err := gs.getRulesWithFilterRego(rule, respStr, path) - if err != nil && !strings.Contains(err.Error(), "404 Not Found") { - return err - } - rule.Rule = rawRego - rule.ResourceEnumerator = filterRego - gs.Rules = append(gs.Rules, *rule) - return nil -} - -func (gs *GitRegoStore) getRulesWithRawRego(rule *opapolicy.PolicyRule, respStr string, path string) (string, error) { - if err := JSONDecoder(respStr).Decode(rule); err != nil { - return "", err - } - rawRegoPath := path[:strings.LastIndex(path, "/")] + "/raw.rego" - respString, err := HttpGetter(gs.httpClient, rawRegoPath) - if err != nil { - return "", err - } - return respString, nil -} - -func (gs *GitRegoStore) getRulesWithFilterRego(rule *opapolicy.PolicyRule, respStr string, path string) (string, error) { - if err := JSONDecoder(respStr).Decode(rule); err != nil { - return "", err - } - rawRegoPath := path[:strings.LastIndex(path, "/")] + "/filter.rego" - respString, err := HttpGetter(gs.httpClient, rawRegoPath) - if err != nil { - return "", err - } - return respString, nil -} - // ======================== set Objects From Release ============================================= -func (gs *GitRegoStore) setObjectsFromReleaseLoop() error { +func (gs *GitRegoStore) setObjects() error { var wg sync.WaitGroup wg.Add(1) var e error @@ -392,68 +248,6 @@ func (gs *GitRegoStore) setControlRuleRelations(respStr string) error { return nil } -func (gs *GitRegoStore) lockAll() { - gs.frameworksLock.Lock() - gs.controlsLock.Lock() - gs.controlRelationsLock.Lock() - gs.frameworkRelationsLock.Lock() - gs.rulesLock.Lock() - gs.attackTracksLock.Lock() - gs.systemPostureExceptionPoliciesLock.Lock() - gs.DefaultConfigInputsLock.Lock() -} - -func (gs *GitRegoStore) rLockAll() { - gs.frameworksLock.RLock() - gs.controlsLock.RLock() - gs.controlRelationsLock.RLock() - gs.frameworkRelationsLock.RLock() - gs.rulesLock.RLock() - gs.attackTracksLock.RLock() - gs.systemPostureExceptionPoliciesLock.RLock() - gs.DefaultConfigInputsLock.RLock() -} - -func (gs *GitRegoStore) unlockAll() { - // unlock acquired mutexes in the reverse order of locking - gs.DefaultConfigInputsLock.Unlock() - gs.systemPostureExceptionPoliciesLock.Unlock() - gs.attackTracksLock.Unlock() - gs.rulesLock.Unlock() - gs.frameworkRelationsLock.Unlock() - gs.controlRelationsLock.Unlock() - gs.controlsLock.Unlock() - gs.frameworksLock.Unlock() -} - -func (gs *GitRegoStore) rUnlockAll() { - // unlock acquired mutexes in the reverse order of locking - gs.DefaultConfigInputsLock.RUnlock() - gs.systemPostureExceptionPoliciesLock.RUnlock() - gs.frameworkRelationsLock.RUnlock() - gs.attackTracksLock.RUnlock() - gs.rulesLock.RUnlock() - gs.controlRelationsLock.RUnlock() - gs.controlsLock.RUnlock() - gs.frameworksLock.RUnlock() -} - -func (gs *GitRegoStore) copyData(other *GitRegoStore) { - other.rLockAll() - defer other.rUnlockAll() - gs.lockAll() - defer gs.unlockAll() - - gs.Frameworks = other.Frameworks - gs.Controls = other.Controls - gs.Rules = other.Rules - gs.AttackTracks = other.AttackTracks - gs.SystemPostureExceptionPolicies = other.SystemPostureExceptionPolicies - gs.DefaultConfigInputs = other.DefaultConfigInputs - gs.ControlRuleRelations = other.ControlRuleRelations - gs.FrameworkControlRelations = other.FrameworkControlRelations -} - // JSONDecoder returns JSON decoder for given string func JSONDecoder(origin string) *json.Decoder { dec := json.NewDecoder(strings.NewReader(origin)) diff --git a/gitregostore/gitstoreutils_test.go b/gitregostore/gitstoreutils_test.go index facc0c0a5..0e008981b 100644 --- a/gitregostore/gitstoreutils_test.go +++ b/gitregostore/gitstoreutils_test.go @@ -106,7 +106,7 @@ func Test_isControlID(t *testing.T) { } } -func TestGitRegoStore_setURL(t *testing.T) { +func TestNewGitRegoStore(t *testing.T) { type fields struct { BaseUrl string Owner string @@ -121,19 +121,19 @@ func TestGitRegoStore_setURL(t *testing.T) { wantedURL string }{ { - name: "setURL 00", + name: "Check Prod gitregostore", fields: fields{ BaseUrl: "https://github.com", Owner: "kubescape", Repository: "regolibrary", - Branch: "releases", - Path: "latest/download", - Tag: "", + Branch: "", + Path: "releases", + Tag: "latest/download", }, wantedURL: "https://github.com/kubescape/regolibrary/releases/latest/download", }, { - name: "setURL 01", + name: "Check Dev gitregostore", fields: fields{ BaseUrl: "https://raw.githubusercontent.com", Owner: "kubescape", @@ -147,18 +147,14 @@ func TestGitRegoStore_setURL(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - gs := &GitRegoStore{ - BaseUrl: tt.fields.BaseUrl, - Owner: tt.fields.Owner, - Repository: tt.fields.Repository, - Branch: tt.fields.Branch, - Path: tt.fields.Path, - Tag: tt.fields.Tag, - } - gs.setURL() + + gs := NewGitRegoStore(tt.fields.BaseUrl, tt.fields.Owner, tt.fields.Repository, tt.fields.Path, tt.fields.Tag, tt.fields.Branch, 5) if gs.URL != tt.wantedURL { t.Errorf("setURL() = %v, want %v", gs.URL, tt.wantedURL) } + gs.SetRegoObjects() + gs_tests(t, gs) + }) } } From 6d65bf3f0fdd8b2a2601d47abe9c600c746b9cdd Mon Sep 17 00:00:00 2001 From: kooomix Date: Thu, 22 Jun 2023 08:46:28 +0300 Subject: [PATCH 11/48] removed backward compatibility for framework name and control ids --- gitregostore/backwardCompatibility.go | 193 --------------------- gitregostore/backwardCompatibility_test.go | 73 -------- gitregostore/gitstoremethods.go | 16 +- gitregostore/gitstoremethods_test.go | 4 +- 4 files changed, 8 insertions(+), 278 deletions(-) delete mode 100644 gitregostore/backwardCompatibility.go delete mode 100644 gitregostore/backwardCompatibility_test.go diff --git a/gitregostore/backwardCompatibility.go b/gitregostore/backwardCompatibility.go deleted file mode 100644 index c31569c14..000000000 --- a/gitregostore/backwardCompatibility.go +++ /dev/null @@ -1,193 +0,0 @@ -package gitregostore - -import ( - "strings" -) - -// oldControlIdsMapping - maps old cis ids to new generated ids for backward compatibility. -// key = old id. value = new id. -var oldControlIdsMapping = map[string]string{ - "CIS-1.1.1": "C-0092", - "CIS-1.1.2": "C-0093", - "CIS-1.1.3": "C-0094", - "CIS-1.1.4": "C-0095", - "CIS-1.1.5": "C-0096", - "CIS-1.1.6": "C-0097", - "CIS-1.1.7": "C-0098", - "CIS-1.1.8": "C-0099", - "CIS-1.1.9": "C-0100", - "CIS-1.1.10": "C-0101", - "CIS-1.1.11": "C-0102", - "CIS-1.1.12": "C-0103", - "CIS-1.1.13": "C-0104", - "CIS-1.1.14": "C-0105", - "CIS-1.1.15": "C-0106", - "CIS-1.1.16": "C-0107", - "CIS-1.1.17": "C-0108", - "CIS-1.1.18": "C-0109", - "CIS-1.1.19": "C-0110", - "CIS-1.1.20": "C-0111", - "CIS-1.1.21": "C-0112", - "CIS-1.2.1": "C-0113", - "CIS-1.2.2": "C-0114", - "CIS-1.2.3": "C-0115", - "CIS-1.2.4": "C-0116", - "CIS-1.2.5": "C-0117", - "CIS-1.2.6": "C-0118", - "CIS-1.2.7": "C-0119", - "CIS-1.2.8": "C-0120", - "CIS-1.2.9": "C-0121", - "CIS-1.2.10": "C-0122", - "CIS-1.2.11": "C-0123", - "CIS-1.2.12": "C-0124", - "CIS-1.2.13": "C-0125", - "CIS-1.2.14": "C-0126", - "CIS-1.2.15": "C-0127", - "CIS-1.2.16": "C-0128", - "CIS-1.2.17": "C-0129", - "CIS-1.2.18": "C-0130", - "CIS-1.2.19": "C-0131", - "CIS-1.2.20": "C-0132", - "CIS-1.2.21": "C-0133", - "CIS-1.2.22": "C-0134", - "CIS-1.2.23": "C-0135", - "CIS-1.2.24": "C-0136", - "CIS-1.2.25": "C-0137", - "CIS-1.2.26": "C-0138", - "CIS-1.2.27": "C-0139", - "CIS-1.2.28": "C-0140", - "CIS-1.2.29": "C-0141", - "CIS-1.2.30": "C-0142", - "CIS-1.2.31": "C-0143", - "CIS-1.3.1": "C-0144", - "CIS-1.3.2": "C-0145", - "CIS-1.3.3": "C-0146", - "CIS-1.3.4": "C-0147", - "CIS-1.3.5": "C-0148", - "CIS-1.3.6": "C-0149", - "CIS-1.3.7": "C-0150", - "CIS-1.4.1": "C-0151", - "CIS-1.4.2": "C-0152", - "CIS-2.1": "C-0153", - "CIS-2.2": "C-0154", - "CIS-2.3": "C-0155", - "CIS-2.4": "C-0156", - "CIS-2.5": "C-0157", - "CIS-2.6": "C-0158", - "CIS-2.7": "C-0159", - "CIS-3.2.1": "C-0160", - "CIS-3.2.2": "C-0161", - "CIS-4.1.1": "C-0162", - "CIS-4.1.2": "C-0163", - "CIS-4.1.3": "C-0164", - "CIS-4.1.4": "C-0165", - "CIS-4.1.5": "C-0166", - "CIS-4.1.6": "C-0167", - "CIS-4.1.7": "C-0168", - "CIS-4.1.8": "C-0169", - "CIS-4.1.9": "C-0170", - "CIS-4.1.10": "C-0171", - "CIS-4.2.1": "C-0172", - "CIS-4.2.2": "C-0173", - "CIS-4.2.3": "C-0174", - "CIS-4.2.4": "C-0175", - "CIS-4.2.5": "C-0176", - "CIS-4.2.6": "C-0177", - "CIS-4.2.7": "C-0178", - "CIS-4.2.8": "C-0179", - "CIS-4.2.9": "C-0180", - "CIS-4.2.10": "C-0181", - "CIS-4.2.11": "C-0182", - "CIS-4.2.12": "C-0183", - "CIS-4.2.13": "C-0184", - "CIS-5.1.1": "C-0185", - "CIS-5.1.2": "C-0186", - "CIS-5.1.3": "C-0187", - "CIS-5.1.4": "C-0188", - "CIS-5.1.5": "C-0189", - "CIS-5.1.6": "C-0190", - "CIS-5.1.8": "C-0191", - "CIS-5.2.1": "C-0192", - "CIS-5.2.2": "C-0193", - "CIS-5.2.3": "C-0194", - "CIS-5.2.4": "C-0195", - "CIS-5.2.5": "C-0196", - "CIS-5.2.6": "C-0197", - "CIS-5.2.7": "C-0198", - "CIS-5.2.8": "C-0199", - "CIS-5.2.9": "C-0200", - "CIS-5.2.10": "C-0201", - "CIS-5.2.11": "C-0202", - "CIS-5.2.12": "C-0203", - "CIS-5.2.13": "C-0204", - "CIS-5.3.1": "C-0205", - "CIS-5.3.2": "C-0206", - "CIS-5.4.1": "C-0207", - "CIS-5.4.2": "C-0208", - "CIS-5.7.1": "C-0209", - "CIS-5.7.2": "C-0210", - "CIS-5.7.3": "C-0211", - "CIS-5.7.4": "C-0212", -} - -const ( - cisFrameworkOldName = "CIS" - cisFrameworkNewName = "cis-v1.23-t1.0.1" -) - -// reverseMap - get a map[string]string typed struct and invert key and values. -func reverseMap(in map[string]string) map[string]string { - - n := make(map[string]string, len(oldControlIdsMapping)) - for k, v := range oldControlIdsMapping { - n[v] = k - } - - return n -} - -// Hold inverted control ids. -// key = new id. value = old id. -var invertedOldControlIdsMapping = reverseMap(oldControlIdsMapping) - -// newControlID - look for new controlID in oldControlIdsMapping. If doesn't exist, return the sent controlID. -func newControlID(controlID string) string { - if newControlID, exist := oldControlIdsMapping[strings.ToUpper(controlID)]; exist { - return newControlID - } - - return controlID - -} - -// newFrameworkName - convert old cis name to new one, if exist, otherwise return frameworkName -func newFrameworkName(frameworkName string) string { - if strings.EqualFold(frameworkName, cisFrameworkOldName) { - return cisFrameworkNewName - } - - return frameworkName -} - -// baseControlName - get control name from cis control name structure "[old_cis_id] [controlName]". -func baseControlName(controlID string, controlName string) string { - - if oldControlID, exist := invertedOldControlIdsMapping[strings.ToUpper(controlID)]; exist { - return strings.Replace(controlName, strings.ToUpper(oldControlID)+" ", "", -1) - } - - return controlName - -} - -// // getNewControlName - build new control name "[old_cis_id] [controlName]" if the controlID is new and was originally a cis id, otherwise return controlName -// func newControlName(controlID string, controlName string) string { - -// if value, exist := invertedOldControlIdsMapping[strings.ToUpper(controlID)]; exist { - -// // if new control id was found, construct new name. -// return strings.ToUpper(value) + " " + controlName -// -// return controlName -// -// } diff --git a/gitregostore/backwardCompatibility_test.go b/gitregostore/backwardCompatibility_test.go deleted file mode 100644 index 1e2c3fa2d..000000000 --- a/gitregostore/backwardCompatibility_test.go +++ /dev/null @@ -1,73 +0,0 @@ -package gitregostore - -import ( - "testing" - - "github.com/alecthomas/assert/v2" -) - -func TestGetNewControlID(t *testing.T) { - controlIDS_tests := []struct { - name string - controlID string - expectedRes string - }{ - { - name: "ControlID_exists_in_mapping_uppercase", - controlID: "CIS-1.1.1", - expectedRes: "C-0092", - }, - { - name: "ControlID_exists_in_mapping_lowercase", - controlID: "cis-1.1.1", - expectedRes: "C-0092", - }, - { - name: "ControlID_doestexists_in_mapping", - controlID: "IDontExist", - expectedRes: "IDontExist", - }, - } - - for _, tt := range controlIDS_tests { - t.Run(tt.name, func(t *testing.T) { - res := newControlID(tt.controlID) - assert.Equal(t, tt.expectedRes, res) - }) - } -} - -func TestBaseControlName(t *testing.T) { - controlIDS_tests := []struct { - name string - controlID string - controlName string - expectedRes string - }{ - { - name: "ControlID_cis_uppercase", - controlID: "C-0092", - controlName: "CIS-1.1.1 Control Name A", - expectedRes: "Control Name A", - }, - { - name: "ControlID_cis_lowercase", - controlID: "c-0092", - controlName: "CIS-1.1.1 Control Name B", - expectedRes: "Control Name B", - }, - { - name: "ControlID_not_cis", - controlID: "NotRelevant", - controlName: "NotCIS name", - expectedRes: "NotCIS name", - }, - } - - for _, tt := range controlIDS_tests { - t.Run(tt.name, func(t *testing.T) { - res := baseControlName(tt.controlID, tt.controlName) - assert.Equal(t, tt.expectedRes, res) - }) - } -} diff --git a/gitregostore/gitstoremethods.go b/gitregostore/gitstoremethods.go index 8316f575d..dcdbea4d5 100644 --- a/gitregostore/gitstoremethods.go +++ b/gitregostore/gitstoremethods.go @@ -13,9 +13,8 @@ import ( ) const ( - supportBackwardCompatibility = true - TypeCompliance = "compliance" - TypeSecurity = "security" + TypeCompliance = "compliance" + TypeSecurity = "security" ) // ============================================================= @@ -96,8 +95,7 @@ func (gs *GitRegoStore) GetOPAControlByName(controlName string) (*opapolicy.Cont for _, controlToPin := range gs.Controls { // If backward compatibility is supported, extract from patched control name the new name. - if !strings.EqualFold(controlToPin.Name, controlName) && - (!supportBackwardCompatibility || !strings.EqualFold(controlToPin.Name, baseControlName(controlToPin.ControlID, controlName))) { + if !strings.EqualFold(controlToPin.Name, controlName) { continue } @@ -126,8 +124,7 @@ func (gs *GitRegoStore) GetOPAControlByID(controlID string) (*opapolicy.Control, func (gs *GitRegoStore) getOPAControlByID(controlID string) (*opapolicy.Control, error) { for _, controlToPin := range gs.Controls { // If backward compatibility is supported, try to find if the controlID sent has a new controlID - if !strings.EqualFold(controlToPin.ControlID, controlID) && - (!supportBackwardCompatibility || !strings.EqualFold(controlToPin.ControlID, newControlID(controlID))) { + if !strings.EqualFold(controlToPin.ControlID, controlID) { continue } @@ -158,8 +155,7 @@ func (gs *GitRegoStore) GetOPAControlByFrameworkNameAndControlName(frameworkName for _, controlToPin := range fw.Controls { // If backward compatibility is supported, extract from patched control name the new name. - if !strings.EqualFold(controlToPin.Name, controlName) && - (!supportBackwardCompatibility || !strings.EqualFold(controlToPin.Name, baseControlName(controlToPin.ControlID, controlName))) { + if !strings.EqualFold(controlToPin.Name, controlName) { continue } @@ -383,7 +379,7 @@ func (gs *GitRegoStore) getOPAFrameworkByName(frameworkName string) (*opapolicy. for _, frameworkToPin := range gs.Frameworks { // If backward compatibility is supported,try to compare the new CIS name. - if !strings.EqualFold(frameworkToPin.Name, frameworkName) && (!supportBackwardCompatibilityFramework || !strings.EqualFold(frameworkToPin.Name, newFrameworkName(frameworkName))) { + if !strings.EqualFold(frameworkToPin.Name, frameworkName) { continue } diff --git a/gitregostore/gitstoremethods_test.go b/gitregostore/gitstoremethods_test.go index a04151525..dcbe82fa3 100644 --- a/gitregostore/gitstoremethods_test.go +++ b/gitregostore/gitstoremethods_test.go @@ -233,8 +233,8 @@ func TestGetOPAFrameworkByName(t *testing.T) { require.NoError(t, gs.SetRegoObjects()) }) - t.Run("shoud retrieve CIS framework", func(t *testing.T) { - _, err := gs.GetOPAFrameworkByName("CIS") + t.Run("shoud retrieve 'cis-v1.23-t1.0.1'' framework", func(t *testing.T) { + _, err := gs.GetOPAFrameworkByName("cis-v1.23-t1.0.1") require.NoErrorf(t, err, "failed to get framework object: %v", err, ) From 10d2a40239a2fe1129323757da251bf17d0597e3 Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Thu, 22 Jun 2023 10:00:54 +0300 Subject: [PATCH 12/48] only download security frameworks from a certain version Signed-off-by: YiscahLevySilas1 --- gitregostore/gitstoreutils.go | 41 +++++++++++++++----- gitregostore/gitstoreutils_test.go | 60 ++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 9 deletions(-) diff --git a/gitregostore/gitstoreutils.go b/gitregostore/gitstoreutils.go index eefc1cdf7..4646406ee 100644 --- a/gitregostore/gitstoreutils.go +++ b/gitregostore/gitstoreutils.go @@ -32,7 +32,8 @@ const ( defaultConfigInputsFileName = "default_config_inputs.json" systemPostureExceptionFileName = "exceptions.json" - controlIDRegex = `^(?:[a-z]+|[A-Z]+)(?:[\-][v]?(?:[0-9][\.]?)+)(?:[\-]?[0-9][\.]?)+$` + controlIDRegex = `^(?:[a-z]+|[A-Z]+)(?:[\-][v]?(?:[0-9][\.]?)+)(?:[\-]?[0-9][\.]?)+$` + earliestTagWithSecurityFrameworks = "v1.0.282-rc.0" ) var ( @@ -154,21 +155,34 @@ func (gs *GitRegoStore) setFrameworks(respStr string) error { if err := JSONDecoder(respStr).Decode(&frameworks); err != nil { return err } - respStr1, err := HttpGetter(gs.httpClient, fmt.Sprintf("%s/%s", gs.URL, gs.stripExtention(securityFrameworksJsonFileName))) - if err != nil { - return fmt.Errorf("error getting: %s from: '%s' ,error: %s", securityFrameworksJsonFileName, gs.URL, err) - } - securityFrameworks := []opapolicy.Framework{} - if err := JSONDecoder(respStr1).Decode(&securityFrameworks); err != nil { - return err + // from a certain tag we have security frameworks + if gs.versionHasSecurityFrameworks() { + respStr1, err := HttpGetter(gs.httpClient, fmt.Sprintf("%s/%s", gs.URL, gs.stripExtention(securityFrameworksJsonFileName))) + if err != nil { + return fmt.Errorf("error getting: %s from: '%s' ,error: %s", securityFrameworksJsonFileName, gs.URL, err) + } + securityFrameworks := []opapolicy.Framework{} + if err := JSONDecoder(respStr1).Decode(&securityFrameworks); err != nil { + return err + } + frameworks = append(frameworks, securityFrameworks...) } gs.frameworksLock.Lock() defer gs.frameworksLock.Unlock() - gs.Frameworks = append(frameworks, securityFrameworks...) + gs.Frameworks = frameworks return nil } +func (gs *GitRegoStore) versionHasSecurityFrameworks() bool { + // check if tag contains numbers + if !hasNumbers(gs.Tag) { + return true + } + tag := strings.Split(gs.Tag, "/")[1] + return tag >= earliestTagWithSecurityFrameworks +} + func (gs *GitRegoStore) setAttackTracks(respStr string) error { attacktracks := []v1alpha1.AttackTrack{} if err := JSONDecoder(respStr).Decode(&attacktracks); err != nil { @@ -312,3 +326,12 @@ func isControlID(c string) bool { return controlIDRegexCompiled.MatchString(c) } + +func hasNumbers(s string) bool { + for _, char := range s { + if char >= '0' && char <= '9' { + return true + } + } + return false +} diff --git a/gitregostore/gitstoreutils_test.go b/gitregostore/gitstoreutils_test.go index 0e008981b..af4d5c5b2 100644 --- a/gitregostore/gitstoreutils_test.go +++ b/gitregostore/gitstoreutils_test.go @@ -255,3 +255,63 @@ func TestSetControl(t *testing.T) { t.Errorf("Expected 1 control, but got: %d", len(store.Controls)) } } + +func TestVersionHasSecurityFrameworks(t *testing.T) { + testCases := []struct { + tag string + expectedValue bool + }{ + {"download/v1.0.202", false}, // Expected: false, because tag < earliestTagWithSecurityFrameworks + {"download/v1.0.283", true}, // Expected: true, because tag > earliestTagWithSecurityFrameworks + {"download/v1.0.283-rc.0", true}, // Expected: true, because tag > earliestTagWithSecurityFrameworks + {"download/v1.0.283-rc.2", true}, // Expected: true, because tag > earliestTagWithSecurityFrameworks + {"download/v1.0.282-rc.0", true}, // Expected: true, because tag = earliestTagWithSecurityFrameworks + {"download/v2.0.202", true}, // Expected: true, because tag > earliestTagWithSecurityFrameworks + {"download/v2.0.202-rc.0", true}, // Expected: true, because tag > earliestTagWithSecurityFrameworks + {"latest/download", true}, // Expected: true, because !hasNumbers(gs.Tag) is true + {"/", true}, // Expected: true, because !hasNumbers(gs.Tag) is true + {"", true}, // Expected: true, because !hasNumbers(gs.Tag) is true + } + + for _, tc := range testCases { + gs := &GitRegoStore{ + Tag: tc.tag, + } + + actualValue := gs.versionHasSecurityFrameworks() + + if actualValue != tc.expectedValue { + t.Errorf("For tag '%s', expected %t, but got %t", tc.tag, tc.expectedValue, actualValue) + } + } +} + +func TestHasNumbers(t *testing.T) { + testCases := []struct { + input string + expectedResult bool + }{ + {"download/v1.0.202", true}, // Expected: true, because input contains numbers + {"download/v1.0.283-rc.0", true}, // Expected: true, because input contains numbers + {"abc", false}, // Expected: false, because input does not contain numbers + {"123", true}, // Expected: true, because input contains numbers + {"!@#$%", false}, // Expected: false, because input does not contain numbers + {"", false}, // Expected: false, because input is empty + {"123abc!@#", true}, // Expected: true, because input contains numbers + {"12 34", true}, // Expected: true, because input contains numbers + {" 56 ", true}, // Expected: true, because input contains numbers + {"", false}, // Expected: false, because input is empty + {"/", false}, // Expected: false, because input does not contain numbers + {"", false}, // Expected: false, because input does not contain numbers + {"latest/download", false}, // Expected: false, because input does not contain numbers + + } + + for _, tc := range testCases { + actualResult := hasNumbers(tc.input) + + if actualResult != tc.expectedResult { + t.Errorf("For input '%s', expected %t, but got %t", tc.input, tc.expectedResult, actualResult) + } + } +} From b641a59de6e84f21a0ec75d9543b22f1e39c216c Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Thu, 22 Jun 2023 10:09:18 +0300 Subject: [PATCH 13/48] add case to test Signed-off-by: YiscahLevySilas1 --- gitregostore/gitstoreutils_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gitregostore/gitstoreutils_test.go b/gitregostore/gitstoreutils_test.go index af4d5c5b2..1b5f7f58d 100644 --- a/gitregostore/gitstoreutils_test.go +++ b/gitregostore/gitstoreutils_test.go @@ -262,6 +262,8 @@ func TestVersionHasSecurityFrameworks(t *testing.T) { expectedValue bool }{ {"download/v1.0.202", false}, // Expected: false, because tag < earliestTagWithSecurityFrameworks + {"download/v1.0.1", false}, // Expected: false, because tag < earliestTagWithSecurityFrameworks + {"download/v1.1.1", true}, // Expected: true, because tag > earliestTagWithSecurityFrameworks {"download/v1.0.283", true}, // Expected: true, because tag > earliestTagWithSecurityFrameworks {"download/v1.0.283-rc.0", true}, // Expected: true, because tag > earliestTagWithSecurityFrameworks {"download/v1.0.283-rc.2", true}, // Expected: true, because tag > earliestTagWithSecurityFrameworks From 9c75a9f704e439d98baad7c4be311d31aa28501d Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Thu, 22 Jun 2023 11:25:42 +0300 Subject: [PATCH 14/48] add control C-0255 Signed-off-by: YiscahLevySilas1 add missing fields to control Signed-off-by: YiscahLevySilas1 --- controls/C-0255-workloadwithsecretaccess.json | 8 +-- frameworks/security.json | 10 ++- rules/workload-mounted-secrets/raw.rego | 70 +++++++++++++++++++ .../rule.metadata.json | 50 +++++++++++++ .../test/failed/expected.json | 69 ++++++++++++++++++ .../test/failed/input/pod.yaml | 18 +++++ .../test/failed/input/secret.yaml | 8 +++ .../test/success/expected.json | 1 + 8 files changed, 229 insertions(+), 5 deletions(-) create mode 100644 rules/workload-mounted-secrets/raw.rego create mode 100644 rules/workload-mounted-secrets/rule.metadata.json create mode 100644 rules/workload-mounted-secrets/test/failed/expected.json create mode 100644 rules/workload-mounted-secrets/test/failed/input/pod.yaml create mode 100644 rules/workload-mounted-secrets/test/failed/input/secret.yaml create mode 100644 rules/workload-mounted-secrets/test/success/expected.json diff --git a/controls/C-0255-workloadwithsecretaccess.json b/controls/C-0255-workloadwithsecretaccess.json index c18655045..7db121350 100644 --- a/controls/C-0255-workloadwithsecretaccess.json +++ b/controls/C-0255-workloadwithsecretaccess.json @@ -14,10 +14,10 @@ } ] }, - "description": "", - "remediation": "", - "rulesNames": [], - "test": "", + "description": "This control identifies workloads that have mounted secrets. Workloads with secret access can potentially expose sensitive information and increase the risk of unauthorized access to critical resources.", + "remediation": "Review the workloads identified by this control and assess whether it's necessary to mount these secrets. Remove secret access from workloads that don't require it or ensure appropriate access controls are in place to protect sensitive information.", + "rulesNames": ["workload-mounted-secrets"], + "test": "Check if any workload has mounted secrets by inspecting their pod specifications and verifying if secret volumes are defined.", "controlID": "C-0255", "baseScore": 4.0 } \ No newline at end of file diff --git a/frameworks/security.json b/frameworks/security.json index db877b2b1..2530abe20 100644 --- a/frameworks/security.json +++ b/frameworks/security.json @@ -4,13 +4,21 @@ "attributes": { "armoBuiltin": true }, - "typeTags": ["security"], + "typeTags": [ + "security" + ], "activeControls": [ { "controlID": "C-0017", "patch": { "name": "Immutable container filesystem" } + }, + { + "controlID": "C-0255", + "patch": { + "name": "Workload with secret access" + } } ] } \ No newline at end of file diff --git a/rules/workload-mounted-secrets/raw.rego b/rules/workload-mounted-secrets/raw.rego new file mode 100644 index 000000000..76d275cd9 --- /dev/null +++ b/rules/workload-mounted-secrets/raw.rego @@ -0,0 +1,70 @@ +package armo_builtins + +deny[msga] { + resource := input[_] + volumes_path := get_volumes_path(resource) + volumes := object.get(resource, volumes_path, []) + volume := volumes[i] + volume.secret + + secret := input[_] + secret.kind == "Secret" + secret.metadata.name == volume.secret.secretName + is_same_namespace(secret.metadata, resource.metadata) + + # add related ressource + resource_vector := json.patch(resource, [{"op": "add", "path": "relatedObjects", "value": [secret]}]) + + failedPaths := sprintf("%s[%d].secret", [concat(".", volumes_path), i]) + + msga := { + "alertMessage": sprintf("%v: %v has mounted secret", [resource.kind, resource.metadata.name]), + "packagename": "armo_builtins", + "failedPaths": [failedPaths], + "fixPaths":[], + "alertObject": { + "k8sApiObjects": [resource], + "externalObjects": resource_vector + } + } +} + +# get_volume_path - get resource volumes paths for {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} +get_volumes_path(resource) := result { + resource_kinds := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} + resource_kinds[resource.kind] + result = ["spec", "template", "spec", "volumes"] +} + +# get_volumes_path - get resource volumes paths for "Pod" +get_volumes_path(resource) := result { + resource.kind == "Pod" + result = ["spec", "volumes"] +} + +# get_volumes_path - get resource volumes paths for "CronJob" +get_volumes_path(resource) := result { + resource.kind == "CronJob" + result = ["spec", "jobTemplate", "spec", "template", "spec", "volumes"] +} + + + +is_same_namespace(metadata1, metadata2) { + metadata1.namespace == metadata2.namespace +} + +is_same_namespace(metadata1, metadata2) { + not metadata1.namespace + not metadata2.namespace +} + +is_same_namespace(metadata1, metadata2) { + not metadata2.namespace + metadata1.namespace == "default" +} + +is_same_namespace(metadata1, metadata2) { + not metadata1.namespace + metadata2.namespace == "default" +} \ No newline at end of file diff --git a/rules/workload-mounted-secrets/rule.metadata.json b/rules/workload-mounted-secrets/rule.metadata.json new file mode 100644 index 000000000..8f561c805 --- /dev/null +++ b/rules/workload-mounted-secrets/rule.metadata.json @@ -0,0 +1,50 @@ +{ + "name": "workload-mounted-secrets", + "attributes": { + "armoBuiltin": true + }, + "ruleLanguage": "Rego", + "match": [ + { + "apiGroups": [ + "" + ], + "apiVersions": [ + "v1" + ], + "resources": [ + "Pod", + "Secret" + ] + }, + { + "apiGroups": [ + "apps" + ], + "apiVersions": [ + "v1" + ], + "resources": [ + "Deployment", + "ReplicaSet", + "DaemonSet", + "StatefulSet" + ] + }, + { + "apiGroups": [ + "batch" + ], + "apiVersions": [ + "*" + ], + "resources": [ + "Job", + "CronJob" + ] + } + ], + "description": "fails if workload mounts secrets", + "remediation": "", + "ruleQuery": "armo_builtins" +} diff --git a/rules/workload-mounted-secrets/test/failed/expected.json b/rules/workload-mounted-secrets/test/failed/expected.json new file mode 100644 index 000000000..28d919472 --- /dev/null +++ b/rules/workload-mounted-secrets/test/failed/expected.json @@ -0,0 +1,69 @@ +[ + { + "alertMessage": "Pod: mypod has mounted secret", + "failedPaths": [ + "spec.volumes[0].secret" + ], + "fixPaths": [], + "ruleStatus": "", + "packagename": "armo_builtins", + "alertScore": 0, + "alertObject": { + "k8sApiObjects": [ + { + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "name": "mypod" + } + } + ], + "externalObjects": { + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "name": "mypod", + "namespace": "default" + }, + "relatedObjects": [ + { + "apiVersion": "v1", + "data": { + "password": "MWYyZDFlMmU2N2Rm", + "username": "YWRtaW4=" + }, + "kind": "Secret", + "metadata": { + "name": "mysecret" + }, + "type": "Opaque" + } + ], + "spec": { + "containers": [ + { + "image": "redis", + "name": "mypod", + "volumeMounts": [ + { + "mountPath": "/etc/foo", + "name": "foo", + "readOnly": true + } + ] + } + ], + "volumes": [ + { + "name": "foo", + "secret": { + "optional": true, + "secretName": "mysecret" + } + } + ] + } + } + } + } +] \ No newline at end of file diff --git a/rules/workload-mounted-secrets/test/failed/input/pod.yaml b/rules/workload-mounted-secrets/test/failed/input/pod.yaml new file mode 100644 index 000000000..ec5b3ddf3 --- /dev/null +++ b/rules/workload-mounted-secrets/test/failed/input/pod.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Pod +metadata: + name: mypod + namespace: default +spec: + containers: + - name: mypod + image: redis + volumeMounts: + - name: foo + mountPath: "/etc/foo" + readOnly: true + volumes: + - name: foo + secret: + secretName: mysecret + optional: true \ No newline at end of file diff --git a/rules/workload-mounted-secrets/test/failed/input/secret.yaml b/rules/workload-mounted-secrets/test/failed/input/secret.yaml new file mode 100644 index 000000000..721bffd05 --- /dev/null +++ b/rules/workload-mounted-secrets/test/failed/input/secret.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Secret +metadata: + name: mysecret +type: Opaque +data: + username: YWRtaW4= + password: MWYyZDFlMmU2N2Rm \ No newline at end of file diff --git a/rules/workload-mounted-secrets/test/success/expected.json b/rules/workload-mounted-secrets/test/success/expected.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/rules/workload-mounted-secrets/test/success/expected.json @@ -0,0 +1 @@ +[] From 5113772e83611550f2be220cf390d7e3cc121f9a Mon Sep 17 00:00:00 2001 From: Alessio Greggi Date: Wed, 21 Jun 2023 13:42:20 +0200 Subject: [PATCH 15/48] test: add k8s resource validation Signed-off-by: Alessio Greggi --- testrunner/go.mod | 3 ++ testrunner/go.sum | 4 +++ testrunner/opaprocessor/processorutils.go | 40 +++++++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/testrunner/go.mod b/testrunner/go.mod index 7aa706fd3..7fb8d8fef 100644 --- a/testrunner/go.mod +++ b/testrunner/go.mod @@ -12,6 +12,8 @@ require ( gopkg.in/yaml.v3 v3.0.1 ) +require github.com/santhosh-tekuri/jsonschema/v5 v5.1.1 // indirect + require ( cloud.google.com/go v0.102.1 // indirect cloud.google.com/go/compute v1.7.0 // indirect @@ -95,6 +97,7 @@ require ( github.com/tchap/go-patricia/v2 v2.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/yannh/kubeconform v0.6.2 github.com/yashtewari/glob-intersection v0.1.0 // indirect go.opencensus.io v0.23.0 // indirect go.uber.org/atomic v1.7.0 // indirect diff --git a/testrunner/go.sum b/testrunner/go.sum index ef2223980..60d22354e 100644 --- a/testrunner/go.sum +++ b/testrunner/go.sum @@ -438,6 +438,8 @@ github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqn github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/santhosh-tekuri/jsonschema/v5 v5.1.1 h1:lEOLY2vyGIqKWUI9nzsOJRV3mb3WC9dXYORsLEUcoeY= +github.com/santhosh-tekuri/jsonschema/v5 v5.1.1/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= @@ -489,6 +491,8 @@ github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMc github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/yannh/kubeconform v0.6.2 h1:xjUxiCcqTBofTsM3UT6fNb/tKRfqjakNfWvHRa3sGOo= +github.com/yannh/kubeconform v0.6.2/go.mod h1:4E6oaL+lh7KgCG2SaOabeeAFBkyKu5D9ab0OEekGcbs= github.com/yashtewari/glob-intersection v0.1.0 h1:6gJvMYQlTDOL3dMsPF6J0+26vwX9MB8/1q3uAdhmTrg= github.com/yashtewari/glob-intersection v0.1.0/go.mod h1:LK7pIC3piUjovexikBbJ26Yml7g8xa5bsjfx2v1fwok= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/testrunner/opaprocessor/processorutils.go b/testrunner/opaprocessor/processorutils.go index 11f830325..159e4442c 100644 --- a/testrunner/opaprocessor/processorutils.go +++ b/testrunner/opaprocessor/processorutils.go @@ -16,6 +16,8 @@ import ( "github.com/kubescape/opa-utils/resources" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/yannh/kubeconform/pkg/resource" + "github.com/yannh/kubeconform/pkg/validator" "gopkg.in/yaml.v3" ) @@ -42,6 +44,37 @@ func convertYamlToJson(i interface{}) interface{} { return i } +// validateInputResource return an error in case the provided k8s resource is not considered valid. +// It uses packages from kubeconform project in order to validate resources. +func validateInputResource(res []byte) error { + k8sResource := resource.Resource{ + Bytes: res, + } + schemaLocation := []string{} + var val validator.Validator + val, err := validator.New(schemaLocation, + validator.Opts{ + Cache: "", + Debug: false, + SkipTLS: false, + SkipKinds: map[string]struct{}{}, + RejectKinds: map[string]struct{}{}, + KubernetesVersion: "master", + Strict: false, + IgnoreMissingSchemas: true, + }, + ) + if err != nil { + return err + } + + result := val.ValidateResource(k8sResource) + if result.Err != nil { + return result.Err + } + return nil +} + func GetInputRawResources(dir string, policyRule *reporthandling.PolicyRule) ([]map[string]interface{}, error) { var IMetadataResources []workloadinterface.IMetadata @@ -53,6 +86,7 @@ func GetInputRawResources(dir string, policyRule *reporthandling.PolicyRule) ([] if resp == nil { return nil, fmt.Errorf("resource is nil") } + metadataResource := objectsenvelopes.NewObject(resp) // if metadataResource.GetNamespace() == "" { // metadataResource.SetNamespace("default") @@ -86,6 +120,12 @@ func GetMockContentFromFile(filename string) (string, error) { if err != nil { return "", err } + + // validate input resource using kubeconform packages + if err = validateInputResource(mockContent); err != nil { + return "", err + } + var body interface{} if err := yaml.Unmarshal([]byte(mockContent), &body); err != nil { return "", err From 8edcfd45c7093f809982e0f02bb05a27c67e9092 Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Mon, 26 Jun 2023 11:45:52 +0300 Subject: [PATCH 16/48] update severity Signed-off-by: YiscahLevySilas1 --- controls/C-0255-workloadwithsecretaccess.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controls/C-0255-workloadwithsecretaccess.json b/controls/C-0255-workloadwithsecretaccess.json index 7db121350..2349a734c 100644 --- a/controls/C-0255-workloadwithsecretaccess.json +++ b/controls/C-0255-workloadwithsecretaccess.json @@ -19,5 +19,5 @@ "rulesNames": ["workload-mounted-secrets"], "test": "Check if any workload has mounted secrets by inspecting their pod specifications and verifying if secret volumes are defined.", "controlID": "C-0255", - "baseScore": 4.0 + "baseScore": 8.0 } \ No newline at end of file From 7666fdda3d9962ac161c8193c642497382b2b1a6 Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Mon, 26 Jun 2023 11:47:37 +0300 Subject: [PATCH 17/48] update description Signed-off-by: YiscahLevySilas1 --- controls/C-0255-workloadwithsecretaccess.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controls/C-0255-workloadwithsecretaccess.json b/controls/C-0255-workloadwithsecretaccess.json index 2349a734c..54098517e 100644 --- a/controls/C-0255-workloadwithsecretaccess.json +++ b/controls/C-0255-workloadwithsecretaccess.json @@ -17,7 +17,7 @@ "description": "This control identifies workloads that have mounted secrets. Workloads with secret access can potentially expose sensitive information and increase the risk of unauthorized access to critical resources.", "remediation": "Review the workloads identified by this control and assess whether it's necessary to mount these secrets. Remove secret access from workloads that don't require it or ensure appropriate access controls are in place to protect sensitive information.", "rulesNames": ["workload-mounted-secrets"], - "test": "Check if any workload has mounted secrets by inspecting their pod specifications and verifying if secret volumes are defined.", + "test": "Check if any workload has mounted secrets by inspecting their specifications and verifying if secret volumes are defined.", "controlID": "C-0255", "baseScore": 8.0 } \ No newline at end of file From 615bd28e9fef8b45d98ad6a4e5c149d86433d54d Mon Sep 17 00:00:00 2001 From: kooomix Date: Mon, 26 Jun 2023 12:09:14 +0300 Subject: [PATCH 18/48] minor rule fix --- .../passed_rolebinding_one_subject/input/rolebinding.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/rules/ensure-default-service-accounts-has-only-default-roles/test/passed_rolebinding_one_subject/input/rolebinding.yaml b/rules/ensure-default-service-accounts-has-only-default-roles/test/passed_rolebinding_one_subject/input/rolebinding.yaml index fc3b02ef1..eaeb7e332 100644 --- a/rules/ensure-default-service-accounts-has-only-default-roles/test/passed_rolebinding_one_subject/input/rolebinding.yaml +++ b/rules/ensure-default-service-accounts-has-only-default-roles/test/passed_rolebinding_one_subject/input/rolebinding.yaml @@ -8,4 +8,8 @@ metadata: subjects: - kind: ServiceAccount name: default - namespace: default \ No newline at end of file + namespace: default +roleRef: + kind: ClusterRole + name: test + apiGroup: rbac.authorization.k8s.io \ No newline at end of file From f46cc3e23adef8378cfc620be6ea775748567094 Mon Sep 17 00:00:00 2001 From: kooomix Date: Mon, 26 Jun 2023 08:20:31 +0300 Subject: [PATCH 19/48] add control C-0258 Signed-off-by: kooomix --- controls/C-0258-configmapaccess.json | 10 +-- frameworks/security.json | 6 ++ rules/workload-mounted-configmap/raw.rego | 67 +++++++++++++++++++ .../rule.metadata.json | 50 ++++++++++++++ .../test/failed_pod/expected.json | 24 +++++++ .../test/failed_pod/input/configmap.yaml | 8 +++ .../test/failed_pod/input/pod.yaml | 23 +++++++ .../expected.json | 1 + .../input/configmap.yaml | 8 +++ .../input/pod.yaml | 23 +++++++ .../test/success_no_configmap/expected.json | 1 + .../test/success_no_configmap/input/pod.yaml | 18 +++++ 12 files changed, 234 insertions(+), 5 deletions(-) create mode 100644 rules/workload-mounted-configmap/raw.rego create mode 100644 rules/workload-mounted-configmap/rule.metadata.json create mode 100644 rules/workload-mounted-configmap/test/failed_pod/expected.json create mode 100644 rules/workload-mounted-configmap/test/failed_pod/input/configmap.yaml create mode 100644 rules/workload-mounted-configmap/test/failed_pod/input/pod.yaml create mode 100644 rules/workload-mounted-configmap/test/success_different_namespaces/expected.json create mode 100644 rules/workload-mounted-configmap/test/success_different_namespaces/input/configmap.yaml create mode 100644 rules/workload-mounted-configmap/test/success_different_namespaces/input/pod.yaml create mode 100644 rules/workload-mounted-configmap/test/success_no_configmap/expected.json create mode 100644 rules/workload-mounted-configmap/test/success_no_configmap/input/pod.yaml diff --git a/controls/C-0258-configmapaccess.json b/controls/C-0258-configmapaccess.json index 4c857b17f..b183f0292 100644 --- a/controls/C-0258-configmapaccess.json +++ b/controls/C-0258-configmapaccess.json @@ -1,5 +1,5 @@ { - "name": "ConfigMap access", + "name": "Workload with ConfigMap access", "attributes": { "armoBuiltin": true, "controlTypeTags": [ @@ -14,10 +14,10 @@ } ] }, - "description": "", - "remediation": "", - "rulesNames": [], - "test": "", + "description": "This control detects workloads that have mounted ConfigMaps. Workloads with ConfigMap access can potentially expose sensitive information and elevate the risk of unauthorized access to critical resources.", + "remediation": "Review the workloads identified by this control and assess whether it's necessary to mount these configMaps. Remove configMaps access from workloads that don't require it or ensure appropriate access controls are in place to protect sensitive information.", + "rulesNames": ["workload-mounted-configmap"], + "test": "Check if any workload has mounted secrets by inspecting their specifications and verifying if secret volumes are defined", "controlID": "C-0258", "baseScore": 4.0 } \ No newline at end of file diff --git a/frameworks/security.json b/frameworks/security.json index db877b2b1..589b87301 100644 --- a/frameworks/security.json +++ b/frameworks/security.json @@ -11,6 +11,12 @@ "patch": { "name": "Immutable container filesystem" } + }, + { + "controlID": "C-0258", + "patch": { + "name": "Workload with configMap access" + } } ] } \ No newline at end of file diff --git a/rules/workload-mounted-configmap/raw.rego b/rules/workload-mounted-configmap/raw.rego new file mode 100644 index 000000000..ab6b9cfd8 --- /dev/null +++ b/rules/workload-mounted-configmap/raw.rego @@ -0,0 +1,67 @@ +package armo_builtins + +deny[msga] { + resource := input[_] + volumes_path := get_volumes_path(resource) + volumes := object.get(resource, volumes_path, []) + volume := volumes[i] + volume.configMap + + configMap := input[_] + configMap.kind == "ConfigMap" + configMap.metadata.name == volume.configMap.name + is_same_namespace(configMap.metadata, resource.metadata) + + + failedPaths := sprintf("%s[%d].configMap", [concat(".", volumes_path), i]) + + msga := { + "alertMessage": sprintf("%v: %v has mounted configMap", [resource.kind, resource.metadata.name]), + "packagename": "armo_builtins", + "failedPaths": [failedPaths], + "fixPaths":[], + "alertObject": { + "k8sApiObjects": [resource] +} + } +} + +# get_volume_path - get resource volumes paths for {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} +get_volumes_path(resource) := result { + resource_kinds := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} + resource_kinds[resource.kind] + result = ["spec", "template", "spec", "volumes"] +} + +# get_volumes_path - get resource volumes paths for "Pod" +get_volumes_path(resource) := result { + resource.kind == "Pod" + result = ["spec", "volumes"] +} + +# get_volumes_path - get resource volumes paths for "CronJob" +get_volumes_path(resource) := result { + resource.kind == "CronJob" + result = ["spec", "jobTemplate", "spec", "template", "spec", "volumes"] +} + + + +is_same_namespace(metadata1, metadata2) { + metadata1.namespace == metadata2.namespace +} + +is_same_namespace(metadata1, metadata2) { + not metadata1.namespace + not metadata2.namespace +} + +is_same_namespace(metadata1, metadata2) { + not metadata2.namespace + metadata1.namespace == "default" +} + +is_same_namespace(metadata1, metadata2) { + not metadata1.namespace + metadata2.namespace == "default" +} \ No newline at end of file diff --git a/rules/workload-mounted-configmap/rule.metadata.json b/rules/workload-mounted-configmap/rule.metadata.json new file mode 100644 index 000000000..acef14c9c --- /dev/null +++ b/rules/workload-mounted-configmap/rule.metadata.json @@ -0,0 +1,50 @@ +{ + "name": "workload-mounted-configmap", + "attributes": { + "armoBuiltin": true + }, + "ruleLanguage": "Rego", + "match": [ + { + "apiGroups": [ + "" + ], + "apiVersions": [ + "v1" + ], + "resources": [ + "Pod", + "ConfigMap" + ] + }, + { + "apiGroups": [ + "apps" + ], + "apiVersions": [ + "v1" + ], + "resources": [ + "Deployment", + "ReplicaSet", + "DaemonSet", + "StatefulSet" + ] + }, + { + "apiGroups": [ + "batch" + ], + "apiVersions": [ + "*" + ], + "resources": [ + "Job", + "CronJob" + ] + } + ], + "description": "fails if workload mounts ConfigMaps", + "remediation": "", + "ruleQuery": "armo_builtins" +} \ No newline at end of file diff --git a/rules/workload-mounted-configmap/test/failed_pod/expected.json b/rules/workload-mounted-configmap/test/failed_pod/expected.json new file mode 100644 index 000000000..40ef922c8 --- /dev/null +++ b/rules/workload-mounted-configmap/test/failed_pod/expected.json @@ -0,0 +1,24 @@ +[ + { + "alertMessage": "Pod: mypod has mounted configMap", + "failedPaths": [ + "spec.volumes[1].configMap" + ], + "fixPaths": [], + "ruleStatus": "", + "packagename": "armo_builtins", + "alertScore": 0, + "alertObject": { + "k8sApiObjects": [ + { + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "name": "mypod" + } + } + ] + + } + } +] \ No newline at end of file diff --git a/rules/workload-mounted-configmap/test/failed_pod/input/configmap.yaml b/rules/workload-mounted-configmap/test/failed_pod/input/configmap.yaml new file mode 100644 index 000000000..c5fd26646 --- /dev/null +++ b/rules/workload-mounted-configmap/test/failed_pod/input/configmap.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: myconfigmap + namespace: mynamespace +data: + key1: value1 + key2: value2 \ No newline at end of file diff --git a/rules/workload-mounted-configmap/test/failed_pod/input/pod.yaml b/rules/workload-mounted-configmap/test/failed_pod/input/pod.yaml new file mode 100644 index 000000000..eb6ee4dd5 --- /dev/null +++ b/rules/workload-mounted-configmap/test/failed_pod/input/pod.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: Pod +metadata: + name: mypod + namespace: mynamespace +spec: + containers: + - name: mypod + image: redis + volumeMounts: + - name: foo + mountPath: "/etc/foo" + readOnly: true + - name: configvolume + mountPath: "/etc/foo" + volumes: + - name: foo + secret: + secretName: mysecret + optional: true + - name: configvolume + configMap: + name: myconfigmap \ No newline at end of file diff --git a/rules/workload-mounted-configmap/test/success_different_namespaces/expected.json b/rules/workload-mounted-configmap/test/success_different_namespaces/expected.json new file mode 100644 index 000000000..0637a088a --- /dev/null +++ b/rules/workload-mounted-configmap/test/success_different_namespaces/expected.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/rules/workload-mounted-configmap/test/success_different_namespaces/input/configmap.yaml b/rules/workload-mounted-configmap/test/success_different_namespaces/input/configmap.yaml new file mode 100644 index 000000000..a25762322 --- /dev/null +++ b/rules/workload-mounted-configmap/test/success_different_namespaces/input/configmap.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: myconfigmap + namespace: mynamespace1 +data: + key1: value1 + key2: value2 \ No newline at end of file diff --git a/rules/workload-mounted-configmap/test/success_different_namespaces/input/pod.yaml b/rules/workload-mounted-configmap/test/success_different_namespaces/input/pod.yaml new file mode 100644 index 000000000..eb6ee4dd5 --- /dev/null +++ b/rules/workload-mounted-configmap/test/success_different_namespaces/input/pod.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: Pod +metadata: + name: mypod + namespace: mynamespace +spec: + containers: + - name: mypod + image: redis + volumeMounts: + - name: foo + mountPath: "/etc/foo" + readOnly: true + - name: configvolume + mountPath: "/etc/foo" + volumes: + - name: foo + secret: + secretName: mysecret + optional: true + - name: configvolume + configMap: + name: myconfigmap \ No newline at end of file diff --git a/rules/workload-mounted-configmap/test/success_no_configmap/expected.json b/rules/workload-mounted-configmap/test/success_no_configmap/expected.json new file mode 100644 index 000000000..0637a088a --- /dev/null +++ b/rules/workload-mounted-configmap/test/success_no_configmap/expected.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/rules/workload-mounted-configmap/test/success_no_configmap/input/pod.yaml b/rules/workload-mounted-configmap/test/success_no_configmap/input/pod.yaml new file mode 100644 index 000000000..ec5b3ddf3 --- /dev/null +++ b/rules/workload-mounted-configmap/test/success_no_configmap/input/pod.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Pod +metadata: + name: mypod + namespace: default +spec: + containers: + - name: mypod + image: redis + volumeMounts: + - name: foo + mountPath: "/etc/foo" + readOnly: true + volumes: + - name: foo + secret: + secretName: mysecret + optional: true \ No newline at end of file From 9c78da6702a5b4c0c20f64164bf6fb610bb04160 Mon Sep 17 00:00:00 2001 From: kooomix Date: Mon, 26 Jun 2023 08:35:04 +0300 Subject: [PATCH 20/48] add control C-0259 to security framework Signed-off-by: kooomix --- controls/C-0259-workloadwithcredentialaccess.json | 8 ++++---- frameworks/security.json | 6 ++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/controls/C-0259-workloadwithcredentialaccess.json b/controls/C-0259-workloadwithcredentialaccess.json index eca60a6d5..ef60a80fe 100644 --- a/controls/C-0259-workloadwithcredentialaccess.json +++ b/controls/C-0259-workloadwithcredentialaccess.json @@ -14,10 +14,10 @@ } ] }, - "description": "", - "remediation": "", - "rulesNames": [], - "test": "", + "description": "This control checks if workloads specifications have sensitive information in their environment variables.", + "remediation": "Use Kubernetes secrets or Key Management Systems to store credentials.", + "rulesNames": ["rule-credentials-in-env-var"], + "test": "Check if the workload has sensitive information in environment variables, by using list of known sensitive key names.", "controlID": "C-0259", "baseScore": 8.0 } \ No newline at end of file diff --git a/frameworks/security.json b/frameworks/security.json index 589b87301..a6f18fc07 100644 --- a/frameworks/security.json +++ b/frameworks/security.json @@ -17,6 +17,12 @@ "patch": { "name": "Workload with configMap access" } + }, + { + "controlID": "C-0259", + "patch": { + "name": "Workload with credential access" + } } ] } \ No newline at end of file From 3d1d6eb6ae5ddc5efa912d8232d659bd69ba148e Mon Sep 17 00:00:00 2001 From: kooomix Date: Mon, 26 Jun 2023 10:54:59 +0300 Subject: [PATCH 21/48] Revert "add control C-0259 to security framework" This reverts commit 522f5ed5335af268eae646a6c129ab29a8eb8db0. Signed-off-by: kooomix --- controls/C-0259-workloadwithcredentialaccess.json | 8 ++++---- frameworks/security.json | 6 ------ 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/controls/C-0259-workloadwithcredentialaccess.json b/controls/C-0259-workloadwithcredentialaccess.json index ef60a80fe..eca60a6d5 100644 --- a/controls/C-0259-workloadwithcredentialaccess.json +++ b/controls/C-0259-workloadwithcredentialaccess.json @@ -14,10 +14,10 @@ } ] }, - "description": "This control checks if workloads specifications have sensitive information in their environment variables.", - "remediation": "Use Kubernetes secrets or Key Management Systems to store credentials.", - "rulesNames": ["rule-credentials-in-env-var"], - "test": "Check if the workload has sensitive information in environment variables, by using list of known sensitive key names.", + "description": "", + "remediation": "", + "rulesNames": [], + "test": "", "controlID": "C-0259", "baseScore": 8.0 } \ No newline at end of file diff --git a/frameworks/security.json b/frameworks/security.json index a6f18fc07..589b87301 100644 --- a/frameworks/security.json +++ b/frameworks/security.json @@ -17,12 +17,6 @@ "patch": { "name": "Workload with configMap access" } - }, - { - "controlID": "C-0259", - "patch": { - "name": "Workload with credential access" - } } ] } \ No newline at end of file From 4d4129d96da19e5dfd7b1858fac9475d1b9a3c52 Mon Sep 17 00:00:00 2001 From: kooomix Date: Mon, 26 Jun 2023 08:45:10 +0300 Subject: [PATCH 22/48] merge Signed-off-by: kooomix --- go.work.sum | 922 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 922 insertions(+) diff --git a/go.work.sum b/go.work.sum index 34d69fc58..36f3e7196 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,35 +1,957 @@ +bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= +bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg= +github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v56.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= +github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= +github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= +github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= +github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= +github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= +github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= +github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= +github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= +github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= +github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= +github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= +github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= +github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= +github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= +github.com/Microsoft/hcsshim v0.9.3/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= +github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= +github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= +github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= +github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/alecthomas/assert/v2 v2.2.0/go.mod h1:b/+1DI2Q6NckYi+3mXyH3wFb8qG37K/DuK80n7WefXA= github.com/alecthomas/repr v0.1.0/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= +github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armosec/armoapi-go v0.0.98/go.mod h1:v7rUl9eo5qL3kHxiP8tFCyRYERUGPgm2rwTIqkVOouw= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= +github.com/aws/aws-sdk-go v1.43.16/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/aws/aws-sdk-go v1.44.51 h1:jO9hoLynZOrMM4dj0KjeKIK+c6PA+HQbKoHOkAEye2Y= github.com/aws/aws-sdk-go v1.44.51/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= +github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= +github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= +github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= +github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= +github.com/bytecodealliance/wasmtime-go v0.36.0/go.mod h1:q320gUxqyI8yB+ZqRuaJOEnGkAnHh6WtJjMaT2CW4wI= github.com/bytecodealliance/wasmtime-go v1.0.0/go.mod h1:jjlqQbWUfVSbehpErw3UoWFndBXRRMvfikYH6KsCwOg= +github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= +github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= +github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= +github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= +github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= +github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= +github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= +github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= +github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= +github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= +github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= +github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= +github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= +github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= +github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= +github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E= +github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= +github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= +github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI= +github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= +github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= +github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= +github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= +github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= +github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= +github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8= +github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= +github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= +github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= +github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= +github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= +github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= +github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= +github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= +github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= +github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c= +github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s= +github.com/containerd/containerd v1.6.1/go.mod h1:1nJz5xCZPusx6jJU8Frfct988y0NpumIq9ODB0kLtoE= +github.com/containerd/containerd v1.6.6/go.mod h1:ZoP1geJldzCVY3Tonoz7b1IXk8rIX0Nltt5QE4OMNk0= github.com/containerd/containerd v1.6.8/go.mod h1:By6p5KqPK0/7/CgO/A6t/Gz+CUYUu2zf1hUaaymVXB0= +github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= +github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= +github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= +github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= +github.com/containerd/continuity v0.2.2/go.mod h1:pWygW9u7LtS1o4N/Tn0FoCFDIXZ7rxcMX7HX1Dmibvk= +github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= +github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= +github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= +github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= +github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= +github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= +github.com/containerd/go-cni v1.1.0/go.mod h1:Rflh2EJ/++BA2/vY5ao3K6WJRR/bZKsX123aPk+kUtA= +github.com/containerd/go-cni v1.1.3/go.mod h1:Rflh2EJ/++BA2/vY5ao3K6WJRR/bZKsX123aPk+kUtA= +github.com/containerd/go-cni v1.1.6/go.mod h1:BWtoWl5ghVymxu6MBjg79W9NZrCRyHIdUtk4cauMe34= +github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g= +github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= +github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= +github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0= +github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA= +github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow= +github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms= +github.com/containerd/imgcrypt v1.1.3/go.mod h1:/TPA1GIDXMzbj01yd8pIbQiLdQxed5ue1wb8bP7PQu4= +github.com/containerd/imgcrypt v1.1.4/go.mod h1:LorQnPtzL/T0IyCeftcsMEO7AqxUDbdO8j/tSUpgxvo= +github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= +github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= +github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= +github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM= +github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= +github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= +github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= +github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ= +github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= +github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= +github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg= +github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= +github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= +github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y= +github.com/containerd/zfs v0.0.0-20210315114300-dde8f0fda960/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v1.0.1/go.mod h1:AKuhXbN5EzmD4yTNtfSsX3tPcmtrBI6QcRV0NiNt15Y= +github.com/containernetworking/cni v1.1.1/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw= +github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= +github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= +github.com/containernetworking/plugins v1.0.1/go.mod h1:QHCfGpaTwYTbbH+nZXKVTxNBDZcxSOplJT5ico8/FLE= +github.com/containernetworking/plugins v1.1.1/go.mod h1:Sr5TH/eBsGLXK/h71HeLfX19sZPp3ry5uHSkI4LPxV8= +github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= +github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= +github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= +github.com/containers/ocicrypt v1.1.2/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= +github.com/containers/ocicrypt v1.1.3/go.mod h1:xpdkbVAuaH3WzbEabUd5yDsl9SwJA5pABH85425Es2g= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= +github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= +github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= +github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= +github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= +github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= +github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg= +github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= +github.com/dgraph-io/badger/v3 v3.2103.2/go.mod h1:RHo4/GmYcKKh5Lxu63wLEMHJ70Pac2JqZRYGhlyAo2M= +github.com/dgraph-io/ristretto v0.1.0/go.mod h1:fux0lOrBhrVCJd3lcTHsIJhq1T2rokOu6v9Vcb3Q9ug= +github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/distribution/distribution/v3 v3.0.0-20220526142353-ffbd94cbe269/go.mod h1:28YO/VJk9/64+sTGNuYaBjWxrXTPrj0C0XmgTIOjxX4= +github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= +github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v20.10.17+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= +github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= +github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c= +github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= +github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= +github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= +github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk= +github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/foxcpp/go-mockdns v0.0.0-20210729171921-fb145fc6f897/go.mod h1:lgRN6+KxQBawyIghpnl5CezHFGS9VLzvtVlwxvzXTQ4= +github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= +github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= +github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= +github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= +github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-ini/ini v1.66.6/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= +github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= +github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= +github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= +github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= +github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= +github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= +github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= +github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go v2.0.0+incompatible h1:j0GKcs05QVmm7yesiZq2+9cxHkNK9YM6zKx4D2qucQU= +github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= +github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= +github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= +github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/intel/goresctrl v0.2.0/go.mod h1:+CZdzouYFn5EsxgqAQTEzMfwKwuc0fVdMrT9FCCAVRQ= +github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= +github.com/j-keck/arping v1.0.2/go.mod h1:aJbELhR92bSk7tp79AWM/ftfc90EfEi2bQJrbBFOsPw= +github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kubescape/rbac-utils v0.0.17/go.mod h1:pBwjpcrVeuH/no+DiCZWvlhYtCDzd3U0o/hEZKi+eM8= +github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= +github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= +github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.25/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= +github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= +github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= +github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= +github.com/moby/sys/signal v0.6.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg= +github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= +github.com/moby/sys/symlink v0.2.0/go.mod h1:7uZVF2dqJjG/NsClqul95CqKOBRQyYSNnJ6BMgR/gFs= +github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= +github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= +github.com/networkplumbing/go-nft v0.2.0/go.mod h1:HnnM+tYvlGAsMU7yoYwXEVLLiDW9gdMmb5HoGcwpuQs= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= +github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= +github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= +github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= +github.com/open-policy-agent/opa v0.42.0/go.mod h1:MrmoTi/BsKWT58kXlVayBb+rYVeaMwuBm3nYAN3923s= +github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.2-0.20211117181255-693428a734f5/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= +github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= +github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= +github.com/opencontainers/runc v1.1.2/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= +github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= +github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= +github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= +github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= +github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= +github.com/opencontainers/selinux v1.10.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/peterh/liner v0.0.0-20170211195444-bf27d3ba8e1d/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= +github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= +github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= +github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= +github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= +github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= +github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= +github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= +github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= +github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= +github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tchap/go-patricia v2.2.6+incompatible h1:JvoDL7JSoIP2HDE8AbDH3zC8QBPxmzYe32HHy5yQ+Ck= +github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/vektah/gqlparser/v2 v2.4.5/go.mod h1:flJWIR04IMQPGz+BXLrORkrARBxv/rtyIAFvd/MceW0= +github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= +github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= +github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= +github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= +github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= +go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= +go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= +go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= +go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= +go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= +go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= +go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.28.0/go.mod h1:vEhqr0m4eTc+DWxfsXoXue2GBgV2uUwVznkGIHW/e5w= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.32.0/go.mod h1:5eCOqeGphOyz6TsY3ZDNjE33SM/TFAK3RGuCL2naTgY= +go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= +go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs= +go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk= +go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.7.0/go.mod h1:M1hVZHNxcbkAlcvrOMlpQ4YOO3Awf+4N2dxkZL3xm04= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0/go.mod h1:hO1KLR7jcKaDDKDkvI9dP/FIhpmna5lkqPUQdEjFAM8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.7.0/go.mod h1:ceUgdyfNv4h4gLxHR0WNfDiiVmZFodZhZSbOLhpxqXE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0/go.mod h1:keUU7UfnwWTWpJ+FWnyqmogPa82nuU5VUANFq49hlMY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.7.0/go.mod h1:E+/KKhwOSw8yoPxSSuUHG6vKppkvhN+S1Jc7Nib3k3o= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.3.0/go.mod h1:QNX1aly8ehqqX1LEa6YniTU7VY9I6R3X/oPxhGdTceE= +go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= +go.opentelemetry.io/otel/metric v0.30.0/go.mod h1:/ShZ7+TS4dHzDFmfi1kSXMhMVubNoP0oIaBp70J6UXU= +go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= +go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= +go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs= +go.opentelemetry.io/otel/sdk v1.7.0/go.mod h1:uTEOTwaqIVuTGiJN7ii13Ibp75wJmYUDe374q6cZwUU= +go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= +go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= +go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= +go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk= +go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU= +go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg3NAKnUGl9YpQ= +go.opentelemetry.io/proto/otlp v0.16.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/automaxprocs v1.5.1/go.mod h1:BF4eumQw0P9GtnuxxovUd06vwm1o18oMzFtK66vU6XU= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/exp v0.0.0-20230116083435-1de6713980de/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= +google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= +gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= gotest.tools/v3 v3.3.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A= +k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= +k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= +k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= +k8s.io/api v0.22.5/go.mod h1:mEhXyLaSD1qTOf40rRiKXkc+2iCem09rWLlFwhCEiAs= k8s.io/apiextensions-apiserver v0.24.2 h1:/4NEQHKlEz1MlaK/wHT5KMKC9UKYz6NZz6JE6ov4G6k= +k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= +k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= +k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= +k8s.io/apimachinery v0.22.1/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= +k8s.io/apimachinery v0.22.5/go.mod h1:xziclGKwuuJ2RM5/rSFQSYAj0zdbci3DH8kj+WvyN0U= +k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= +k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= +k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= +k8s.io/apiserver v0.22.5/go.mod h1:s2WbtgZAkTKt679sYtSudEQrTGWUSQAPe6MupLnlmaQ= +k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= +k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= +k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= +k8s.io/client-go v0.22.5/go.mod h1:cs6yf/61q2T1SdQL5Rdcjg9J1ElXSwbjSrW2vFImM4Y= +k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0= +k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= +k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= +k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= +k8s.io/component-base v0.22.5/go.mod h1:VK3I+TjuF9eaa+Ln67dKxhGar5ynVbwnGrUiNF4MqCI= +k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= +k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= +k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= +k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= +k8s.io/cri-api v0.23.1/go.mod h1:REJE3PSU0h/LOV1APBrupxrEJqnoxZC8KWzkBUHwrK4= +k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= +k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= +k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= +k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= +k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= +k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= +k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +oras.land/oras-go v1.2.0/go.mod h1:pFNs7oHp2dYsYMSS82HaX5l4mpnGO7hbpPN6EWH2ltc= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= From 39e26b852c3b17bfa673c94662cffd129ee7d7a6 Mon Sep 17 00:00:00 2001 From: kooomix Date: Mon, 26 Jun 2023 08:48:50 +0300 Subject: [PATCH 23/48] add control C-0259 to security framework Signed-off-by: kooomix --- controls/C-0259-workloadwithcredentialaccess.json | 8 ++++---- frameworks/security.json | 6 ++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/controls/C-0259-workloadwithcredentialaccess.json b/controls/C-0259-workloadwithcredentialaccess.json index eca60a6d5..ef60a80fe 100644 --- a/controls/C-0259-workloadwithcredentialaccess.json +++ b/controls/C-0259-workloadwithcredentialaccess.json @@ -14,10 +14,10 @@ } ] }, - "description": "", - "remediation": "", - "rulesNames": [], - "test": "", + "description": "This control checks if workloads specifications have sensitive information in their environment variables.", + "remediation": "Use Kubernetes secrets or Key Management Systems to store credentials.", + "rulesNames": ["rule-credentials-in-env-var"], + "test": "Check if the workload has sensitive information in environment variables, by using list of known sensitive key names.", "controlID": "C-0259", "baseScore": 8.0 } \ No newline at end of file diff --git a/frameworks/security.json b/frameworks/security.json index db877b2b1..9cfeb0e71 100644 --- a/frameworks/security.json +++ b/frameworks/security.json @@ -11,6 +11,12 @@ "patch": { "name": "Immutable container filesystem" } + }, + { + "controlID": "C-0259", + "patch": { + "name": "Workload with credential access" + } } ] } \ No newline at end of file From 1541f8f88d99f5b4b2235f81e09f108b7c5352c4 Mon Sep 17 00:00:00 2001 From: kooomix Date: Mon, 26 Jun 2023 13:10:27 +0300 Subject: [PATCH 24/48] updated base score --- controls/C-0258-configmapaccess.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controls/C-0258-configmapaccess.json b/controls/C-0258-configmapaccess.json index b183f0292..cf0e62870 100644 --- a/controls/C-0258-configmapaccess.json +++ b/controls/C-0258-configmapaccess.json @@ -19,5 +19,5 @@ "rulesNames": ["workload-mounted-configmap"], "test": "Check if any workload has mounted secrets by inspecting their specifications and verifying if secret volumes are defined", "controlID": "C-0258", - "baseScore": 4.0 + "baseScore": 5.0 } \ No newline at end of file From 15db0616dee6afb15b9ff5f6b0e655cb6854ac29 Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Mon, 26 Jun 2023 14:38:25 +0300 Subject: [PATCH 25/48] add input to success test Signed-off-by: YiscahLevySilas1 --- .../test/success/input/pod.yaml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 rules/workload-mounted-secrets/test/success/input/pod.yaml diff --git a/rules/workload-mounted-secrets/test/success/input/pod.yaml b/rules/workload-mounted-secrets/test/success/input/pod.yaml new file mode 100644 index 000000000..9b20af164 --- /dev/null +++ b/rules/workload-mounted-secrets/test/success/input/pod.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test-pd +spec: + containers: + - image: k8s.gcr.io/test-webserver + name: test-container + volumeMounts: + - mountPath: /test-pd + name: test-volume + volumes: + - name: test-volume + hostPath: + path: /data + \ No newline at end of file From 25feb2c23d594f5c2193859c52f00d3adce2f791 Mon Sep 17 00:00:00 2001 From: kooomix Date: Wed, 28 Jun 2023 10:55:46 +0300 Subject: [PATCH 26/48] C-0257 --- controls/C-0257-pvcaccess.json | 10 +- frameworks/security.json | 6 ++ rules/workload-mounted-pvc/raw.rego | 94 +++++++++++++++++++ rules/workload-mounted-pvc/rule.metadata.json | 50 ++++++++++ .../test/failed_pod_mounted/expected.json | 24 +++++ .../test/failed_pod_mounted/input/PVC.yaml | 17 ++++ .../test/failed_pod_mounted/input/pod.yaml | 15 +++ .../expected.json | 1 + .../input/PVC.yaml | 17 ++++ .../input/pod.yaml | 16 ++++ .../test/success_no_PVC/expected.json | 1 + .../test/success_no_PVC/input/pod.yaml | 18 ++++ .../expected.json | 1 + .../input/PVC.yaml | 17 ++++ .../input/pod.yaml | 15 +++ 15 files changed, 297 insertions(+), 5 deletions(-) create mode 100644 rules/workload-mounted-pvc/raw.rego create mode 100644 rules/workload-mounted-pvc/rule.metadata.json create mode 100644 rules/workload-mounted-pvc/test/failed_pod_mounted/expected.json create mode 100644 rules/workload-mounted-pvc/test/failed_pod_mounted/input/PVC.yaml create mode 100644 rules/workload-mounted-pvc/test/failed_pod_mounted/input/pod.yaml create mode 100644 rules/workload-mounted-pvc/test/success_different_namespaces/expected.json create mode 100644 rules/workload-mounted-pvc/test/success_different_namespaces/input/PVC.yaml create mode 100644 rules/workload-mounted-pvc/test/success_different_namespaces/input/pod.yaml create mode 100644 rules/workload-mounted-pvc/test/success_no_PVC/expected.json create mode 100644 rules/workload-mounted-pvc/test/success_no_PVC/input/pod.yaml create mode 100644 rules/workload-mounted-pvc/test/success_with_PVC_not_mounted/expected.json create mode 100644 rules/workload-mounted-pvc/test/success_with_PVC_not_mounted/input/PVC.yaml create mode 100644 rules/workload-mounted-pvc/test/success_with_PVC_not_mounted/input/pod.yaml diff --git a/controls/C-0257-pvcaccess.json b/controls/C-0257-pvcaccess.json index 99a0bac53..d2ee83a1b 100644 --- a/controls/C-0257-pvcaccess.json +++ b/controls/C-0257-pvcaccess.json @@ -1,5 +1,5 @@ { - "name": "PVC access", + "name": "Workload with PVC access", "attributes": { "armoBuiltin": true, "controlTypeTags": [ @@ -14,10 +14,10 @@ } ] }, - "description": "", - "remediation": "", - "rulesNames": [], - "test": "", + "description": "This control detects workloads that have mounted PVC. Workloads with PVC access can potentially expose sensitive information and elevate the risk of unauthorized access to critical resources.", + "remediation": "Review the workloads identified by this control and assess whether it's necessary to mount these PVCs. Remove PVC access from workloads that don't require it or ensure appropriate access controls are in place to protect sensitive information.", + "rulesNames": ["workload-mounted-pvc"], + "test": "Check if any workload has mounted PVCs by inspecting their specifications and verifying if PVC volumes are defined", "controlID": "C-0257", "baseScore": 4.0 } \ No newline at end of file diff --git a/frameworks/security.json b/frameworks/security.json index 589b87301..af1d83337 100644 --- a/frameworks/security.json +++ b/frameworks/security.json @@ -17,6 +17,12 @@ "patch": { "name": "Workload with configMap access" } + }, + { + "controlID": "C-0257", + "patch": { + "name": "Workload with PVC access" + } } ] } \ No newline at end of file diff --git a/rules/workload-mounted-pvc/raw.rego b/rules/workload-mounted-pvc/raw.rego new file mode 100644 index 000000000..904c5d25d --- /dev/null +++ b/rules/workload-mounted-pvc/raw.rego @@ -0,0 +1,94 @@ +package armo_builtins + +deny[msga] { + resource := input[_] + volumes_path := get_volumes_path(resource) + volumes := object.get(resource, volumes_path, []) + volume := volumes[i] + volume.persistentVolumeClaim + + PVC := input[_] + PVC.kind == "PersistentVolumeClaim" + PVC.metadata.name == volume.persistentVolumeClaim.claimName + is_same_namespace(PVC.metadata, resource.metadata) + + containers_path := get_containers_path(resource) + containers := object.get(resource, containers_path, []) + container := containers[j] + container.volumeMounts + + # check if volume is mounted + container.volumeMounts[_].name == volume.name + + failedPaths := sprintf("%s[%d].volumeMounts", [concat(".", containers_path), j]) + + msga := { + "alertMessage": sprintf("%v: %v has mounted PVC", [resource.kind, resource.metadata.name]), + "packagename": "armo_builtins", + "failedPaths": [failedPaths], + "fixPaths":[], + "alertObject": { + "k8sApiObjects": [resource] +} + } +} + + +# get_containers_path - get resource containers paths for {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} +get_containers_path(resource) := result { + resource_kinds := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} + resource_kinds[resource.kind] + result = ["spec", "template", "spec", "containers"] +} + +# get_containers_path - get resource containers paths for "Pod" +get_containers_path(resource) := result { + resource.kind == "Pod" + result = ["spec", "containers"] +} + +# get_containers_path - get resource containers paths for "CronJob" +get_containers_path(resource) := result { + resource.kind == "CronJob" + result = ["spec", "jobTemplate", "spec", "template", "spec", "containers"] +} + +# get_volume_path - get resource volumes paths for {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} +get_volumes_path(resource) := result { + resource_kinds := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} + resource_kinds[resource.kind] + result = ["spec", "template", "spec", "volumes"] +} + +# get_volumes_path - get resource volumes paths for "Pod" +get_volumes_path(resource) := result { + resource.kind == "Pod" + result = ["spec", "volumes"] +} + +# get_volumes_path - get resource volumes paths for "CronJob" +get_volumes_path(resource) := result { + resource.kind == "CronJob" + result = ["spec", "jobTemplate", "spec", "template", "spec", "volumes"] +} + + + +is_same_namespace(metadata1, metadata2) { + metadata1.namespace == metadata2.namespace +} + +is_same_namespace(metadata1, metadata2) { + not metadata1.namespace + not metadata2.namespace +} + +is_same_namespace(metadata1, metadata2) { + not metadata2.namespace + metadata1.namespace == "default" +} + +is_same_namespace(metadata1, metadata2) { + not metadata1.namespace + metadata2.namespace == "default" +} \ No newline at end of file diff --git a/rules/workload-mounted-pvc/rule.metadata.json b/rules/workload-mounted-pvc/rule.metadata.json new file mode 100644 index 000000000..acef14c9c --- /dev/null +++ b/rules/workload-mounted-pvc/rule.metadata.json @@ -0,0 +1,50 @@ +{ + "name": "workload-mounted-configmap", + "attributes": { + "armoBuiltin": true + }, + "ruleLanguage": "Rego", + "match": [ + { + "apiGroups": [ + "" + ], + "apiVersions": [ + "v1" + ], + "resources": [ + "Pod", + "ConfigMap" + ] + }, + { + "apiGroups": [ + "apps" + ], + "apiVersions": [ + "v1" + ], + "resources": [ + "Deployment", + "ReplicaSet", + "DaemonSet", + "StatefulSet" + ] + }, + { + "apiGroups": [ + "batch" + ], + "apiVersions": [ + "*" + ], + "resources": [ + "Job", + "CronJob" + ] + } + ], + "description": "fails if workload mounts ConfigMaps", + "remediation": "", + "ruleQuery": "armo_builtins" +} \ No newline at end of file diff --git a/rules/workload-mounted-pvc/test/failed_pod_mounted/expected.json b/rules/workload-mounted-pvc/test/failed_pod_mounted/expected.json new file mode 100644 index 000000000..eefbd7016 --- /dev/null +++ b/rules/workload-mounted-pvc/test/failed_pod_mounted/expected.json @@ -0,0 +1,24 @@ +[ + { + "alertMessage": "Pod: mypod has mounted PVC", + "failedPaths": [ + "spec.containers[0].volumeMounts" + ], + "fixPaths": [], + "ruleStatus": "", + "packagename": "armo_builtins", + "alertScore": 0, + "alertObject": { + "k8sApiObjects": [ + { + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "name": "mypod" + } + } + ] + + } + } +] \ No newline at end of file diff --git a/rules/workload-mounted-pvc/test/failed_pod_mounted/input/PVC.yaml b/rules/workload-mounted-pvc/test/failed_pod_mounted/input/PVC.yaml new file mode 100644 index 000000000..6993c5d8e --- /dev/null +++ b/rules/workload-mounted-pvc/test/failed_pod_mounted/input/PVC.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: myclaim +spec: + accessModes: + - ReadWriteOnce + volumeMode: Filesystem + resources: + requests: + storage: 8Gi + storageClassName: slow + selector: + matchLabels: + release: "stable" + matchExpressions: + - {key: environment, operator: In, values: [dev]} \ No newline at end of file diff --git a/rules/workload-mounted-pvc/test/failed_pod_mounted/input/pod.yaml b/rules/workload-mounted-pvc/test/failed_pod_mounted/input/pod.yaml new file mode 100644 index 000000000..6a6bada6a --- /dev/null +++ b/rules/workload-mounted-pvc/test/failed_pod_mounted/input/pod.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: mypod +spec: + containers: + - name: myfrontend + image: nginx + volumeMounts: + - mountPath: "/var/www/html" + name: mypd + volumes: + - name: mypd + persistentVolumeClaim: + claimName: myclaim \ No newline at end of file diff --git a/rules/workload-mounted-pvc/test/success_different_namespaces/expected.json b/rules/workload-mounted-pvc/test/success_different_namespaces/expected.json new file mode 100644 index 000000000..0637a088a --- /dev/null +++ b/rules/workload-mounted-pvc/test/success_different_namespaces/expected.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/rules/workload-mounted-pvc/test/success_different_namespaces/input/PVC.yaml b/rules/workload-mounted-pvc/test/success_different_namespaces/input/PVC.yaml new file mode 100644 index 000000000..6993c5d8e --- /dev/null +++ b/rules/workload-mounted-pvc/test/success_different_namespaces/input/PVC.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: myclaim +spec: + accessModes: + - ReadWriteOnce + volumeMode: Filesystem + resources: + requests: + storage: 8Gi + storageClassName: slow + selector: + matchLabels: + release: "stable" + matchExpressions: + - {key: environment, operator: In, values: [dev]} \ No newline at end of file diff --git a/rules/workload-mounted-pvc/test/success_different_namespaces/input/pod.yaml b/rules/workload-mounted-pvc/test/success_different_namespaces/input/pod.yaml new file mode 100644 index 000000000..eaabde538 --- /dev/null +++ b/rules/workload-mounted-pvc/test/success_different_namespaces/input/pod.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + name: mypod + namespace: namespace1 +spec: + containers: + - name: myfrontend + image: nginx + volumeMounts: + - mountPath: "/var/www/html" + name: mypd + volumes: + - name: mypd + persistentVolumeClaim: + claimName: myclaim \ No newline at end of file diff --git a/rules/workload-mounted-pvc/test/success_no_PVC/expected.json b/rules/workload-mounted-pvc/test/success_no_PVC/expected.json new file mode 100644 index 000000000..0637a088a --- /dev/null +++ b/rules/workload-mounted-pvc/test/success_no_PVC/expected.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/rules/workload-mounted-pvc/test/success_no_PVC/input/pod.yaml b/rules/workload-mounted-pvc/test/success_no_PVC/input/pod.yaml new file mode 100644 index 000000000..ec5b3ddf3 --- /dev/null +++ b/rules/workload-mounted-pvc/test/success_no_PVC/input/pod.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Pod +metadata: + name: mypod + namespace: default +spec: + containers: + - name: mypod + image: redis + volumeMounts: + - name: foo + mountPath: "/etc/foo" + readOnly: true + volumes: + - name: foo + secret: + secretName: mysecret + optional: true \ No newline at end of file diff --git a/rules/workload-mounted-pvc/test/success_with_PVC_not_mounted/expected.json b/rules/workload-mounted-pvc/test/success_with_PVC_not_mounted/expected.json new file mode 100644 index 000000000..0637a088a --- /dev/null +++ b/rules/workload-mounted-pvc/test/success_with_PVC_not_mounted/expected.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/rules/workload-mounted-pvc/test/success_with_PVC_not_mounted/input/PVC.yaml b/rules/workload-mounted-pvc/test/success_with_PVC_not_mounted/input/PVC.yaml new file mode 100644 index 000000000..6993c5d8e --- /dev/null +++ b/rules/workload-mounted-pvc/test/success_with_PVC_not_mounted/input/PVC.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: myclaim +spec: + accessModes: + - ReadWriteOnce + volumeMode: Filesystem + resources: + requests: + storage: 8Gi + storageClassName: slow + selector: + matchLabels: + release: "stable" + matchExpressions: + - {key: environment, operator: In, values: [dev]} \ No newline at end of file diff --git a/rules/workload-mounted-pvc/test/success_with_PVC_not_mounted/input/pod.yaml b/rules/workload-mounted-pvc/test/success_with_PVC_not_mounted/input/pod.yaml new file mode 100644 index 000000000..42a1ebb24 --- /dev/null +++ b/rules/workload-mounted-pvc/test/success_with_PVC_not_mounted/input/pod.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: mypod +spec: + containers: + - name: myfrontend + image: nginx + volumeMounts: + - mountPath: "/var/www/html" + name: mypd1 + volumes: + - name: mypd + persistentVolumeClaim: + claimName: myclaim \ No newline at end of file From 903ed6ba5e328e212ccace21bafd6c09fbcedb10 Mon Sep 17 00:00:00 2001 From: kooomix Date: Wed, 28 Jun 2023 11:01:11 +0300 Subject: [PATCH 27/48] fix volume mount --- rules/workload-mounted-configmap/raw.rego | 31 ++++++++++++++++++- .../test/failed_pod/expected.json | 2 +- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/rules/workload-mounted-configmap/raw.rego b/rules/workload-mounted-configmap/raw.rego index ab6b9cfd8..1c9368e85 100644 --- a/rules/workload-mounted-configmap/raw.rego +++ b/rules/workload-mounted-configmap/raw.rego @@ -12,8 +12,16 @@ deny[msga] { configMap.metadata.name == volume.configMap.name is_same_namespace(configMap.metadata, resource.metadata) + containers_path := get_containers_path(resource) + containers := object.get(resource, containers_path, []) + container := containers[j] + container.volumeMounts - failedPaths := sprintf("%s[%d].configMap", [concat(".", volumes_path), i]) + # check if volume is mounted + container.volumeMounts[_].name == volume.name + + failedPaths := sprintf("%s[%d].volumeMounts", [concat(".", containers_path), j]) + msga := { "alertMessage": sprintf("%v: %v has mounted configMap", [resource.kind, resource.metadata.name]), @@ -26,6 +34,27 @@ deny[msga] { } } + + +# get_containers_path - get resource containers paths for {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} +get_containers_path(resource) := result { + resource_kinds := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} + resource_kinds[resource.kind] + result = ["spec", "template", "spec", "containers"] +} + +# get_containers_path - get resource containers paths for "Pod" +get_containers_path(resource) := result { + resource.kind == "Pod" + result = ["spec", "containers"] +} + +# get_containers_path - get resource containers paths for "CronJob" +get_containers_path(resource) := result { + resource.kind == "CronJob" + result = ["spec", "jobTemplate", "spec", "template", "spec", "containers"] +} + # get_volume_path - get resource volumes paths for {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} get_volumes_path(resource) := result { resource_kinds := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} diff --git a/rules/workload-mounted-configmap/test/failed_pod/expected.json b/rules/workload-mounted-configmap/test/failed_pod/expected.json index 40ef922c8..fc1d607bc 100644 --- a/rules/workload-mounted-configmap/test/failed_pod/expected.json +++ b/rules/workload-mounted-configmap/test/failed_pod/expected.json @@ -2,7 +2,7 @@ { "alertMessage": "Pod: mypod has mounted configMap", "failedPaths": [ - "spec.volumes[1].configMap" + "spec.containers[0].volumeMounts" ], "fixPaths": [], "ruleStatus": "", From 8f0051c7bc207ffa675368d129965e11fba8491d Mon Sep 17 00:00:00 2001 From: kooomix Date: Wed, 28 Jun 2023 12:41:16 +0300 Subject: [PATCH 28/48] fix rule name --- rules/workload-mounted-pvc/rule.metadata.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/workload-mounted-pvc/rule.metadata.json b/rules/workload-mounted-pvc/rule.metadata.json index acef14c9c..dc22b0543 100644 --- a/rules/workload-mounted-pvc/rule.metadata.json +++ b/rules/workload-mounted-pvc/rule.metadata.json @@ -1,5 +1,5 @@ { - "name": "workload-mounted-configmap", + "name": "workload-mounted-pvc", "attributes": { "armoBuiltin": true }, @@ -44,7 +44,7 @@ ] } ], - "description": "fails if workload mounts ConfigMaps", + "description": "fails if workload mounts PVC", "remediation": "", "ruleQuery": "armo_builtins" } \ No newline at end of file From 03438abe6a930795affec7b1d357bbe75692b098 Mon Sep 17 00:00:00 2001 From: kooomix Date: Thu, 29 Jun 2023 08:38:35 +0300 Subject: [PATCH 29/48] control C-0260 --- controls/C-0260-missingnetworkpolicy.json | 10 +- frameworks/security.json | 6 ++ .../raw.rego | 98 +++++++++++++++++++ .../rule.metadata.json | 61 ++++++++++++ .../expected.json | 23 +++++ .../input/cronjob.yaml | 17 ++++ .../input/network_policy.yaml | 12 +++ .../expected.json | 26 +++++ .../input/deployment.yaml | 19 ++++ .../input/network_policy.yaml | 12 +++ .../failed_pod_no_matched_label/expected.json | 26 +++++ .../input/network_policy.yaml | 12 +++ .../input/pod.yaml | 10 ++ .../failed_pod_no_networkpolicy/expected.json | 23 +++++ .../input/pod.yaml | 23 +++++ .../success_cronjob_label_match/expected.json | 1 + .../input/cronjob.yaml | 17 ++++ .../input/network_policy.yaml | 12 +++ .../expected.json | 1 + .../input/deployment.yaml | 19 ++++ .../input/network_policy.yaml | 12 +++ .../success_pod_label_match/expected.json | 1 + .../input/network_policy.yaml | 12 +++ .../success_pod_label_match/input/pod.yaml | 10 ++ .../success_pod_no_pod_selector/expected.json | 1 + .../input/network_policy.yaml | 10 ++ .../input/pod.yaml | 10 ++ 27 files changed, 479 insertions(+), 5 deletions(-) create mode 100644 rules/ensure_network_policy_configured_in_labels/raw.rego create mode 100644 rules/ensure_network_policy_configured_in_labels/rule.metadata.json create mode 100644 rules/ensure_network_policy_configured_in_labels/test/failed_cronjob_no_matched_label/expected.json create mode 100644 rules/ensure_network_policy_configured_in_labels/test/failed_cronjob_no_matched_label/input/cronjob.yaml create mode 100644 rules/ensure_network_policy_configured_in_labels/test/failed_cronjob_no_matched_label/input/network_policy.yaml create mode 100644 rules/ensure_network_policy_configured_in_labels/test/failed_deployment_no_matched_label/expected.json create mode 100644 rules/ensure_network_policy_configured_in_labels/test/failed_deployment_no_matched_label/input/deployment.yaml create mode 100644 rules/ensure_network_policy_configured_in_labels/test/failed_deployment_no_matched_label/input/network_policy.yaml create mode 100644 rules/ensure_network_policy_configured_in_labels/test/failed_pod_no_matched_label/expected.json create mode 100644 rules/ensure_network_policy_configured_in_labels/test/failed_pod_no_matched_label/input/network_policy.yaml create mode 100644 rules/ensure_network_policy_configured_in_labels/test/failed_pod_no_matched_label/input/pod.yaml create mode 100644 rules/ensure_network_policy_configured_in_labels/test/failed_pod_no_networkpolicy/expected.json create mode 100644 rules/ensure_network_policy_configured_in_labels/test/failed_pod_no_networkpolicy/input/pod.yaml create mode 100644 rules/ensure_network_policy_configured_in_labels/test/success_cronjob_label_match/expected.json create mode 100644 rules/ensure_network_policy_configured_in_labels/test/success_cronjob_label_match/input/cronjob.yaml create mode 100644 rules/ensure_network_policy_configured_in_labels/test/success_cronjob_label_match/input/network_policy.yaml create mode 100644 rules/ensure_network_policy_configured_in_labels/test/success_deployment_label_match/expected.json create mode 100644 rules/ensure_network_policy_configured_in_labels/test/success_deployment_label_match/input/deployment.yaml create mode 100644 rules/ensure_network_policy_configured_in_labels/test/success_deployment_label_match/input/network_policy.yaml create mode 100644 rules/ensure_network_policy_configured_in_labels/test/success_pod_label_match/expected.json create mode 100644 rules/ensure_network_policy_configured_in_labels/test/success_pod_label_match/input/network_policy.yaml create mode 100644 rules/ensure_network_policy_configured_in_labels/test/success_pod_label_match/input/pod.yaml create mode 100644 rules/ensure_network_policy_configured_in_labels/test/success_pod_no_pod_selector/expected.json create mode 100644 rules/ensure_network_policy_configured_in_labels/test/success_pod_no_pod_selector/input/network_policy.yaml create mode 100644 rules/ensure_network_policy_configured_in_labels/test/success_pod_no_pod_selector/input/pod.yaml diff --git a/controls/C-0260-missingnetworkpolicy.json b/controls/C-0260-missingnetworkpolicy.json index 08af08bc3..a2efffdbd 100644 --- a/controls/C-0260-missingnetworkpolicy.json +++ b/controls/C-0260-missingnetworkpolicy.json @@ -14,10 +14,10 @@ } ] }, - "description": "", - "remediation": "", - "rulesNames": [], - "test": "", + "description": "This control detects workloads that has no NetworkPolicy configured in labels. If a network policy is not configured, it means that your applications might not have necessary control over the traffic to and from the pods, possibly leading to a security vulnerability.", + "remediation": "Review the workloads identified by this control and assess whether it's necessary to configure a network policy for them.", + "rulesNames": ["ensure_network_policy_configured_in_labels"], + "test": "Check that all workloads has a network policy configured in labels.", "controlID": "C-0260", - "baseScore": 4.0 + "baseScore": 5.0 } \ No newline at end of file diff --git a/frameworks/security.json b/frameworks/security.json index af1d83337..ad921350e 100644 --- a/frameworks/security.json +++ b/frameworks/security.json @@ -23,6 +23,12 @@ "patch": { "name": "Workload with PVC access" } + }, + { + "controlID": "C-0260", + "patch": { + "name": "Missing network policy" + } } ] } \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/raw.rego b/rules/ensure_network_policy_configured_in_labels/raw.rego new file mode 100644 index 000000000..c96c25667 --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/raw.rego @@ -0,0 +1,98 @@ +package armo_builtins + + +deny[msga] { + + resources := get_resources(input[_]) + resource := resources[_] + + # getting all networkpolicies + networkpolicies := [networkpolicy | networkpolicy= input[_]; networkpolicy.kind == "NetworkPolicy"] + + # getting all networkpolicies that are connected to workload with label + network_policies_connected_to_workload := [networkpolicy | networkpolicy= networkpolicies[_]; connected_to_network_policy(resource, networkpolicy)] + + # we expect the number of resources to be equal to the number of networkpolicies connected to the workload. If not, deny. + not count(resources) == count(network_policies_connected_to_workload) + + msga := { + "alertMessage": sprintf("%v: no networkpolicy configured in labels", [resource.metadata.name]), + "packagename": "armo_builtins", + "failedPaths": [], + "fixPaths":[], + "alertObject": { + "k8sApiObjects": [resource] + } + } +} + + +# get_resources returns all resources of kind Deployment, ReplicaSet, DaemonSet, StatefulSet, Job, Pod, CronJob +get_resources(resources) := result { + resource_kinds := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} + resource_kinds[resources.kind] + result = [resources] +} + +# get_resources returns all resources of kind Pod +get_resources(resources) := result { + resources.kind == "Pod" + result = [resources] +} + +# get_resources returns all resources of kind CronJob +get_resources(resources) := result { + resources.kind == "CronJob" + result = [resources] +} + +# connected_to_network_policy returns true if the resource is connected to the networkpolicy +connected_to_network_policy(wl, networkpolicy){ + resource_kinds := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} + resource_kinds[wl.kind] + is_same_namespace(networkpolicy.metadata, wl.metadata) + count(networkpolicy.spec.podSelector) > 0 + count({x | networkpolicy.spec.podSelector.matchLabels[x] == wl.spec.template.metadata.labels[x]}) == count(networkpolicy.spec.podSelector.matchLabels) +} + +# connected_to_network_policy returns true if the resource is connected to the networkpolicy +connected_to_network_policy(wl, networkpolicy){ + wl.kind == "Pod" + is_same_namespace(networkpolicy.metadata, wl.metadata) + count(networkpolicy.spec.podSelector) > 0 + count({x | networkpolicy.spec.podSelector.matchLabels[x] == wl.metadata.labels[x]}) == count(networkpolicy.spec.podSelector.matchLabels) +} + +# connected_to_network_policy returns true if the resource is connected to the networkpolicy +connected_to_network_policy(wl, networkpolicy){ + wl.kind == "CronJob" + is_same_namespace(networkpolicy.metadata, wl.metadata) + count(networkpolicy.spec.podSelector) > 0 + count({x | networkpolicy.spec.podSelector.matchLabels[x] == wl.spec.jobTemplate.spec.template.metadata.labels[x]}) == count(networkpolicy.spec.podSelector.matchLabels) +} + +# connected_to_network_policy returns true if the NetworkPolicy has no podSelector. +# if the NetworkPolicy has no podSelector, it is applied to all workloads in the namespace of the NetworkPolicy +connected_to_network_policy(wl, networkpolicy){ + count(networkpolicy.spec.podSelector) == 0 +} + + +is_same_namespace(metadata1, metadata2) { + metadata1.namespace == metadata2.namespace +} + +is_same_namespace(metadata1, metadata2) { + not metadata1.namespace + not metadata2.namespace +} + +is_same_namespace(metadata1, metadata2) { + not metadata2.namespace + metadata1.namespace == "default" +} + +is_same_namespace(metadata1, metadata2) { + not metadata1.namespace + metadata2.namespace == "default" +} \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/rule.metadata.json b/rules/ensure_network_policy_configured_in_labels/rule.metadata.json new file mode 100644 index 000000000..64711b69e --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/rule.metadata.json @@ -0,0 +1,61 @@ +{ + "name": "ensure_network_policy_configured_in_labels", + "attributes": { + "armoBuiltin": true + }, + "ruleLanguage": "Rego", + "match": [ + { + "apiGroups": [ + "" + ], + "apiVersions": [ + "v1" + ], + "resources": [ + "Pod", + "ConfigMap" + ] + }, + { + "apiGroups": [ + "apps" + ], + "apiVersions": [ + "v1" + ], + "resources": [ + "Deployment", + "ReplicaSet", + "DaemonSet", + "StatefulSet" + ] + }, + { + "apiGroups": [ + "batch" + ], + "apiVersions": [ + "*" + ], + "resources": [ + "Job", + "CronJob" + ] + }, + { + "apiGroups": [ + "networking.k8s.io" + ], + "apiVersions": [ + "v1" + ], + "resources": [ + "NetworkPolicy" + ] + } + ], + "description": "fails if no networkpolicy configured in workload labels", + "remediation": "", + "ruleQuery": "armo_builtins" +} \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/failed_cronjob_no_matched_label/expected.json b/rules/ensure_network_policy_configured_in_labels/test/failed_cronjob_no_matched_label/expected.json new file mode 100644 index 000000000..00ed39e97 --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/failed_cronjob_no_matched_label/expected.json @@ -0,0 +1,23 @@ +[ + { + "alertMessage": "my-cronjob: no networkpolicy configured in labels", + "failedPaths": [ + ], + "fixPaths": [], + "ruleStatus": "", + "packagename": "armo_builtins", + "alertScore": 0, + "alertObject": { + "k8sApiObjects": [ + { + "apiVersion": "batch/v1beta1", + "kind": "CronJob", + "metadata": { + "name": "my-cronjob" + } + } + ] + + } + } +] \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/failed_cronjob_no_matched_label/input/cronjob.yaml b/rules/ensure_network_policy_configured_in_labels/test/failed_cronjob_no_matched_label/input/cronjob.yaml new file mode 100644 index 000000000..0adbabc1d --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/failed_cronjob_no_matched_label/input/cronjob.yaml @@ -0,0 +1,17 @@ +apiVersion: batch/v1beta1 +kind: CronJob +metadata: + name: my-cronjob +spec: + schedule: "*/1 * * * *" + jobTemplate: + spec: + template: + metadata: + labels: + job: my-cronjob + spec: + containers: + - name: my-cronjob-container + image: my-cronjob-image + restartPolicy: OnFailure \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/failed_cronjob_no_matched_label/input/network_policy.yaml b/rules/ensure_network_policy_configured_in_labels/test/failed_cronjob_no_matched_label/input/network_policy.yaml new file mode 100644 index 000000000..bccdea356 --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/failed_cronjob_no_matched_label/input/network_policy.yaml @@ -0,0 +1,12 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: my-pod-network-policy +spec: + podSelector: + matchLabels: + app: my-pod1 + ingress: + - ports: + - protocol: TCP + port: 8080 \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/failed_deployment_no_matched_label/expected.json b/rules/ensure_network_policy_configured_in_labels/test/failed_deployment_no_matched_label/expected.json new file mode 100644 index 000000000..10b4824f1 --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/failed_deployment_no_matched_label/expected.json @@ -0,0 +1,26 @@ +[ + { + "alertMessage": "my-deployment: no networkpolicy configured in labels", + "failedPaths": [ + ], + "fixPaths": [], + "ruleStatus": "", + "packagename": "armo_builtins", + "alertScore": 0, + "alertObject": { + "k8sApiObjects": [ + { + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "name": "my-deployment", + "labels": { + "deployment": "my-deployment" + } + } + } + ] + + } + } +] \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/failed_deployment_no_matched_label/input/deployment.yaml b/rules/ensure_network_policy_configured_in_labels/test/failed_deployment_no_matched_label/input/deployment.yaml new file mode 100644 index 000000000..c7b97b9c6 --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/failed_deployment_no_matched_label/input/deployment.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-deployment + labels: + deployment: my-deployment # label for the Deployment itself +spec: + replicas: 3 + selector: + matchLabels: + app: my-app # Used to select the Pods the Deployment should manage + template: + metadata: + labels: + app: my-app # Labels for the Pods created by the Deployment + spec: + containers: + - name: my-app + image: my-app:1.0.0 \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/failed_deployment_no_matched_label/input/network_policy.yaml b/rules/ensure_network_policy_configured_in_labels/test/failed_deployment_no_matched_label/input/network_policy.yaml new file mode 100644 index 000000000..bccdea356 --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/failed_deployment_no_matched_label/input/network_policy.yaml @@ -0,0 +1,12 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: my-pod-network-policy +spec: + podSelector: + matchLabels: + app: my-pod1 + ingress: + - ports: + - protocol: TCP + port: 8080 \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/failed_pod_no_matched_label/expected.json b/rules/ensure_network_policy_configured_in_labels/test/failed_pod_no_matched_label/expected.json new file mode 100644 index 000000000..b367f0e3a --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/failed_pod_no_matched_label/expected.json @@ -0,0 +1,26 @@ +[ + { + "alertMessage": "my-pod: no networkpolicy configured in labels", + "failedPaths": [ + ], + "fixPaths": [], + "ruleStatus": "", + "packagename": "armo_builtins", + "alertScore": 0, + "alertObject": { + "k8sApiObjects": [ + { + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "name": "my-pod", + "labels": { + "app": "my-pod" + } + } + } + ] + + } + } +] \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/failed_pod_no_matched_label/input/network_policy.yaml b/rules/ensure_network_policy_configured_in_labels/test/failed_pod_no_matched_label/input/network_policy.yaml new file mode 100644 index 000000000..bccdea356 --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/failed_pod_no_matched_label/input/network_policy.yaml @@ -0,0 +1,12 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: my-pod-network-policy +spec: + podSelector: + matchLabels: + app: my-pod1 + ingress: + - ports: + - protocol: TCP + port: 8080 \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/failed_pod_no_matched_label/input/pod.yaml b/rules/ensure_network_policy_configured_in_labels/test/failed_pod_no_matched_label/input/pod.yaml new file mode 100644 index 000000000..f99f91caa --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/failed_pod_no_matched_label/input/pod.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Pod +metadata: + name: my-pod + labels: + app: my-pod +spec: + containers: + - name: my-app + image: my-app:1.0.0 \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/failed_pod_no_networkpolicy/expected.json b/rules/ensure_network_policy_configured_in_labels/test/failed_pod_no_networkpolicy/expected.json new file mode 100644 index 000000000..71a18183e --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/failed_pod_no_networkpolicy/expected.json @@ -0,0 +1,23 @@ +[ + { + "alertMessage": "mypod: no networkpolicy configured in labels", + "failedPaths": [ + ], + "fixPaths": [], + "ruleStatus": "", + "packagename": "armo_builtins", + "alertScore": 0, + "alertObject": { + "k8sApiObjects": [ + { + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "name": "mypod" + } + } + ] + + } + } +] \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/failed_pod_no_networkpolicy/input/pod.yaml b/rules/ensure_network_policy_configured_in_labels/test/failed_pod_no_networkpolicy/input/pod.yaml new file mode 100644 index 000000000..eb6ee4dd5 --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/failed_pod_no_networkpolicy/input/pod.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: Pod +metadata: + name: mypod + namespace: mynamespace +spec: + containers: + - name: mypod + image: redis + volumeMounts: + - name: foo + mountPath: "/etc/foo" + readOnly: true + - name: configvolume + mountPath: "/etc/foo" + volumes: + - name: foo + secret: + secretName: mysecret + optional: true + - name: configvolume + configMap: + name: myconfigmap \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/success_cronjob_label_match/expected.json b/rules/ensure_network_policy_configured_in_labels/test/success_cronjob_label_match/expected.json new file mode 100644 index 000000000..0637a088a --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/success_cronjob_label_match/expected.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/success_cronjob_label_match/input/cronjob.yaml b/rules/ensure_network_policy_configured_in_labels/test/success_cronjob_label_match/input/cronjob.yaml new file mode 100644 index 000000000..0adbabc1d --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/success_cronjob_label_match/input/cronjob.yaml @@ -0,0 +1,17 @@ +apiVersion: batch/v1beta1 +kind: CronJob +metadata: + name: my-cronjob +spec: + schedule: "*/1 * * * *" + jobTemplate: + spec: + template: + metadata: + labels: + job: my-cronjob + spec: + containers: + - name: my-cronjob-container + image: my-cronjob-image + restartPolicy: OnFailure \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/success_cronjob_label_match/input/network_policy.yaml b/rules/ensure_network_policy_configured_in_labels/test/success_cronjob_label_match/input/network_policy.yaml new file mode 100644 index 000000000..2c2279434 --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/success_cronjob_label_match/input/network_policy.yaml @@ -0,0 +1,12 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: my-app-network-policy +spec: + podSelector: + matchLabels: + job: my-cronjob + ingress: + - ports: + - protocol: TCP + port: 8080 \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/success_deployment_label_match/expected.json b/rules/ensure_network_policy_configured_in_labels/test/success_deployment_label_match/expected.json new file mode 100644 index 000000000..0637a088a --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/success_deployment_label_match/expected.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/success_deployment_label_match/input/deployment.yaml b/rules/ensure_network_policy_configured_in_labels/test/success_deployment_label_match/input/deployment.yaml new file mode 100644 index 000000000..c7b97b9c6 --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/success_deployment_label_match/input/deployment.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-deployment + labels: + deployment: my-deployment # label for the Deployment itself +spec: + replicas: 3 + selector: + matchLabels: + app: my-app # Used to select the Pods the Deployment should manage + template: + metadata: + labels: + app: my-app # Labels for the Pods created by the Deployment + spec: + containers: + - name: my-app + image: my-app:1.0.0 \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/success_deployment_label_match/input/network_policy.yaml b/rules/ensure_network_policy_configured_in_labels/test/success_deployment_label_match/input/network_policy.yaml new file mode 100644 index 000000000..29b71402d --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/success_deployment_label_match/input/network_policy.yaml @@ -0,0 +1,12 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: my-app-network-policy +spec: + podSelector: + matchLabels: + app: my-app + ingress: + - ports: + - protocol: TCP + port: 8080 \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/success_pod_label_match/expected.json b/rules/ensure_network_policy_configured_in_labels/test/success_pod_label_match/expected.json new file mode 100644 index 000000000..0637a088a --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/success_pod_label_match/expected.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/success_pod_label_match/input/network_policy.yaml b/rules/ensure_network_policy_configured_in_labels/test/success_pod_label_match/input/network_policy.yaml new file mode 100644 index 000000000..a4f4d7b08 --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/success_pod_label_match/input/network_policy.yaml @@ -0,0 +1,12 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: my-pod-network-policy +spec: + podSelector: + matchLabels: + app: my-pod + ingress: + - ports: + - protocol: TCP + port: 8080 \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/success_pod_label_match/input/pod.yaml b/rules/ensure_network_policy_configured_in_labels/test/success_pod_label_match/input/pod.yaml new file mode 100644 index 000000000..f99f91caa --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/success_pod_label_match/input/pod.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Pod +metadata: + name: my-pod + labels: + app: my-pod +spec: + containers: + - name: my-app + image: my-app:1.0.0 \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/success_pod_no_pod_selector/expected.json b/rules/ensure_network_policy_configured_in_labels/test/success_pod_no_pod_selector/expected.json new file mode 100644 index 000000000..0637a088a --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/success_pod_no_pod_selector/expected.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/success_pod_no_pod_selector/input/network_policy.yaml b/rules/ensure_network_policy_configured_in_labels/test/success_pod_no_pod_selector/input/network_policy.yaml new file mode 100644 index 000000000..860ab46e5 --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/success_pod_no_pod_selector/input/network_policy.yaml @@ -0,0 +1,10 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: my-pod-network-policy +spec: + podSelector: {} + ingress: + - ports: + - protocol: TCP + port: 8080 \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/success_pod_no_pod_selector/input/pod.yaml b/rules/ensure_network_policy_configured_in_labels/test/success_pod_no_pod_selector/input/pod.yaml new file mode 100644 index 000000000..f99f91caa --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/success_pod_no_pod_selector/input/pod.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Pod +metadata: + name: my-pod + labels: + app: my-pod +spec: + containers: + - name: my-app + image: my-app:1.0.0 \ No newline at end of file From 58a066c7c86d1ed4ab13ee0b9190c0412c820c0a Mon Sep 17 00:00:00 2001 From: kooomix Date: Thu, 29 Jun 2023 08:53:48 +0300 Subject: [PATCH 30/48] fix volumeMounts Signed-off-by: kooomix --- rules/workload-mounted-configmap/raw.rego | 30 ++++++++++++++++++- .../test/failed_pod/expected.json | 2 +- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/rules/workload-mounted-configmap/raw.rego b/rules/workload-mounted-configmap/raw.rego index ab6b9cfd8..5b5c14e1b 100644 --- a/rules/workload-mounted-configmap/raw.rego +++ b/rules/workload-mounted-configmap/raw.rego @@ -12,8 +12,15 @@ deny[msga] { configMap.metadata.name == volume.configMap.name is_same_namespace(configMap.metadata, resource.metadata) + containers_path := get_containers_path(resource) + containers := object.get(resource, containers_path, []) + container := containers[j] + container.volumeMounts - failedPaths := sprintf("%s[%d].configMap", [concat(".", volumes_path), i]) + # check if volume is mounted + container.volumeMounts[_].name == volume.name + + failedPaths := sprintf("%s[%d].volumeMounts", [concat(".", containers_path), j]) msga := { "alertMessage": sprintf("%v: %v has mounted configMap", [resource.kind, resource.metadata.name]), @@ -26,6 +33,27 @@ deny[msga] { } } + + +# get_containers_path - get resource containers paths for {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} +get_containers_path(resource) := result { + resource_kinds := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} + resource_kinds[resource.kind] + result = ["spec", "template", "spec", "containers"] +} + +# get_containers_path - get resource containers paths for "Pod" +get_containers_path(resource) := result { + resource.kind == "Pod" + result = ["spec", "containers"] +} + +# get_containers_path - get resource containers paths for "CronJob" +get_containers_path(resource) := result { + resource.kind == "CronJob" + result = ["spec", "jobTemplate", "spec", "template", "spec", "containers"] +} + # get_volume_path - get resource volumes paths for {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} get_volumes_path(resource) := result { resource_kinds := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} diff --git a/rules/workload-mounted-configmap/test/failed_pod/expected.json b/rules/workload-mounted-configmap/test/failed_pod/expected.json index 40ef922c8..fc1d607bc 100644 --- a/rules/workload-mounted-configmap/test/failed_pod/expected.json +++ b/rules/workload-mounted-configmap/test/failed_pod/expected.json @@ -2,7 +2,7 @@ { "alertMessage": "Pod: mypod has mounted configMap", "failedPaths": [ - "spec.volumes[1].configMap" + "spec.containers[0].volumeMounts" ], "fixPaths": [], "ruleStatus": "", From 26fdc64effdc67dc5ecbdac45845f168ebaeb21a Mon Sep 17 00:00:00 2001 From: kooomix Date: Thu, 29 Jun 2023 09:05:53 +0300 Subject: [PATCH 31/48] Merge Signed-off-by: kooomix --- attack-tracks/service-destruction.json | 18 ++++ attack-tracks/workload-external-track.json | 38 ++++++++ rules/workload-mounted-configmap/raw.rego | 67 +++++++++++++ .../rule.metadata.json | 50 ++++++++++ .../test/failed_pod/expected.json | 24 +++++ .../test/failed_pod/input/configmap.yaml | 8 ++ .../test/failed_pod/input/pod.yaml | 23 +++++ .../expected.json | 1 + .../input/configmap.yaml | 8 ++ .../input/pod.yaml | 23 +++++ .../test/success_no_configmap/expected.json | 1 + .../test/success_no_configmap/input/pod.yaml | 18 ++++ rules/workload-mounted-pvc/raw.rego | 94 +++++++++++++++++++ rules/workload-mounted-pvc/rule.metadata.json | 50 ++++++++++ .../test/failed_pod_mounted/expected.json | 24 +++++ .../test/failed_pod_mounted/input/PVC.yaml | 17 ++++ .../test/failed_pod_mounted/input/pod.yaml | 15 +++ .../expected.json | 1 + .../input/PVC.yaml | 17 ++++ .../input/pod.yaml | 16 ++++ .../test/success_no_PVC/expected.json | 1 + .../test/success_no_PVC/input/pod.yaml | 18 ++++ .../expected.json | 1 + .../input/PVC.yaml | 17 ++++ .../input/pod.yaml | 15 +++ 25 files changed, 565 insertions(+) create mode 100644 attack-tracks/service-destruction.json create mode 100644 attack-tracks/workload-external-track.json create mode 100644 rules/workload-mounted-configmap/raw.rego create mode 100644 rules/workload-mounted-configmap/rule.metadata.json create mode 100644 rules/workload-mounted-configmap/test/failed_pod/expected.json create mode 100644 rules/workload-mounted-configmap/test/failed_pod/input/configmap.yaml create mode 100644 rules/workload-mounted-configmap/test/failed_pod/input/pod.yaml create mode 100644 rules/workload-mounted-configmap/test/success_different_namespaces/expected.json create mode 100644 rules/workload-mounted-configmap/test/success_different_namespaces/input/configmap.yaml create mode 100644 rules/workload-mounted-configmap/test/success_different_namespaces/input/pod.yaml create mode 100644 rules/workload-mounted-configmap/test/success_no_configmap/expected.json create mode 100644 rules/workload-mounted-configmap/test/success_no_configmap/input/pod.yaml create mode 100644 rules/workload-mounted-pvc/raw.rego create mode 100644 rules/workload-mounted-pvc/rule.metadata.json create mode 100644 rules/workload-mounted-pvc/test/failed_pod_mounted/expected.json create mode 100644 rules/workload-mounted-pvc/test/failed_pod_mounted/input/PVC.yaml create mode 100644 rules/workload-mounted-pvc/test/failed_pod_mounted/input/pod.yaml create mode 100644 rules/workload-mounted-pvc/test/success_different_namespaces/expected.json create mode 100644 rules/workload-mounted-pvc/test/success_different_namespaces/input/PVC.yaml create mode 100644 rules/workload-mounted-pvc/test/success_different_namespaces/input/pod.yaml create mode 100644 rules/workload-mounted-pvc/test/success_no_PVC/expected.json create mode 100644 rules/workload-mounted-pvc/test/success_no_PVC/input/pod.yaml create mode 100644 rules/workload-mounted-pvc/test/success_with_PVC_not_mounted/expected.json create mode 100644 rules/workload-mounted-pvc/test/success_with_PVC_not_mounted/input/PVC.yaml create mode 100644 rules/workload-mounted-pvc/test/success_with_PVC_not_mounted/input/pod.yaml diff --git a/attack-tracks/service-destruction.json b/attack-tracks/service-destruction.json new file mode 100644 index 000000000..745b81164 --- /dev/null +++ b/attack-tracks/service-destruction.json @@ -0,0 +1,18 @@ +{ + "apiVersion": "regolibrary.kubescape/v1alpha1", + "kind": "AttackTrack", + "metadata": { + "name": "service-destruction" + }, + "spec": { + "version": "1.0", + "data": { + "name": "Workload Exposure", + "subSteps": [ + { + "name": "Service Destruction" + } + ] + } + } +} \ No newline at end of file diff --git a/attack-tracks/workload-external-track.json b/attack-tracks/workload-external-track.json new file mode 100644 index 000000000..2018ce2f1 --- /dev/null +++ b/attack-tracks/workload-external-track.json @@ -0,0 +1,38 @@ +{ + "apiVersion": "regolibrary.kubescape/v1alpha1", + "kind": "AttackTrack", + "metadata": { + "name": "workload-external-track" + }, + "spec": { + "version": "1.0", + "data": { + "name": "Workload Exposure", + "subSteps": [ + { + "name": "Vulnerable Image", + "subSteps": [ + { + "name": "Data Access" + }, + { + "name": "Secret Access" + }, + { + "name": "Credential access" + }, + { + "name": "Potential Node exposure" + }, + { + "name": "Persistence" + }, + { + "name": "Network" + } + ] + } + ] + } + } +} \ No newline at end of file diff --git a/rules/workload-mounted-configmap/raw.rego b/rules/workload-mounted-configmap/raw.rego new file mode 100644 index 000000000..ab6b9cfd8 --- /dev/null +++ b/rules/workload-mounted-configmap/raw.rego @@ -0,0 +1,67 @@ +package armo_builtins + +deny[msga] { + resource := input[_] + volumes_path := get_volumes_path(resource) + volumes := object.get(resource, volumes_path, []) + volume := volumes[i] + volume.configMap + + configMap := input[_] + configMap.kind == "ConfigMap" + configMap.metadata.name == volume.configMap.name + is_same_namespace(configMap.metadata, resource.metadata) + + + failedPaths := sprintf("%s[%d].configMap", [concat(".", volumes_path), i]) + + msga := { + "alertMessage": sprintf("%v: %v has mounted configMap", [resource.kind, resource.metadata.name]), + "packagename": "armo_builtins", + "failedPaths": [failedPaths], + "fixPaths":[], + "alertObject": { + "k8sApiObjects": [resource] +} + } +} + +# get_volume_path - get resource volumes paths for {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} +get_volumes_path(resource) := result { + resource_kinds := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} + resource_kinds[resource.kind] + result = ["spec", "template", "spec", "volumes"] +} + +# get_volumes_path - get resource volumes paths for "Pod" +get_volumes_path(resource) := result { + resource.kind == "Pod" + result = ["spec", "volumes"] +} + +# get_volumes_path - get resource volumes paths for "CronJob" +get_volumes_path(resource) := result { + resource.kind == "CronJob" + result = ["spec", "jobTemplate", "spec", "template", "spec", "volumes"] +} + + + +is_same_namespace(metadata1, metadata2) { + metadata1.namespace == metadata2.namespace +} + +is_same_namespace(metadata1, metadata2) { + not metadata1.namespace + not metadata2.namespace +} + +is_same_namespace(metadata1, metadata2) { + not metadata2.namespace + metadata1.namespace == "default" +} + +is_same_namespace(metadata1, metadata2) { + not metadata1.namespace + metadata2.namespace == "default" +} \ No newline at end of file diff --git a/rules/workload-mounted-configmap/rule.metadata.json b/rules/workload-mounted-configmap/rule.metadata.json new file mode 100644 index 000000000..acef14c9c --- /dev/null +++ b/rules/workload-mounted-configmap/rule.metadata.json @@ -0,0 +1,50 @@ +{ + "name": "workload-mounted-configmap", + "attributes": { + "armoBuiltin": true + }, + "ruleLanguage": "Rego", + "match": [ + { + "apiGroups": [ + "" + ], + "apiVersions": [ + "v1" + ], + "resources": [ + "Pod", + "ConfigMap" + ] + }, + { + "apiGroups": [ + "apps" + ], + "apiVersions": [ + "v1" + ], + "resources": [ + "Deployment", + "ReplicaSet", + "DaemonSet", + "StatefulSet" + ] + }, + { + "apiGroups": [ + "batch" + ], + "apiVersions": [ + "*" + ], + "resources": [ + "Job", + "CronJob" + ] + } + ], + "description": "fails if workload mounts ConfigMaps", + "remediation": "", + "ruleQuery": "armo_builtins" +} \ No newline at end of file diff --git a/rules/workload-mounted-configmap/test/failed_pod/expected.json b/rules/workload-mounted-configmap/test/failed_pod/expected.json new file mode 100644 index 000000000..40ef922c8 --- /dev/null +++ b/rules/workload-mounted-configmap/test/failed_pod/expected.json @@ -0,0 +1,24 @@ +[ + { + "alertMessage": "Pod: mypod has mounted configMap", + "failedPaths": [ + "spec.volumes[1].configMap" + ], + "fixPaths": [], + "ruleStatus": "", + "packagename": "armo_builtins", + "alertScore": 0, + "alertObject": { + "k8sApiObjects": [ + { + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "name": "mypod" + } + } + ] + + } + } +] \ No newline at end of file diff --git a/rules/workload-mounted-configmap/test/failed_pod/input/configmap.yaml b/rules/workload-mounted-configmap/test/failed_pod/input/configmap.yaml new file mode 100644 index 000000000..c5fd26646 --- /dev/null +++ b/rules/workload-mounted-configmap/test/failed_pod/input/configmap.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: myconfigmap + namespace: mynamespace +data: + key1: value1 + key2: value2 \ No newline at end of file diff --git a/rules/workload-mounted-configmap/test/failed_pod/input/pod.yaml b/rules/workload-mounted-configmap/test/failed_pod/input/pod.yaml new file mode 100644 index 000000000..eb6ee4dd5 --- /dev/null +++ b/rules/workload-mounted-configmap/test/failed_pod/input/pod.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: Pod +metadata: + name: mypod + namespace: mynamespace +spec: + containers: + - name: mypod + image: redis + volumeMounts: + - name: foo + mountPath: "/etc/foo" + readOnly: true + - name: configvolume + mountPath: "/etc/foo" + volumes: + - name: foo + secret: + secretName: mysecret + optional: true + - name: configvolume + configMap: + name: myconfigmap \ No newline at end of file diff --git a/rules/workload-mounted-configmap/test/success_different_namespaces/expected.json b/rules/workload-mounted-configmap/test/success_different_namespaces/expected.json new file mode 100644 index 000000000..0637a088a --- /dev/null +++ b/rules/workload-mounted-configmap/test/success_different_namespaces/expected.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/rules/workload-mounted-configmap/test/success_different_namespaces/input/configmap.yaml b/rules/workload-mounted-configmap/test/success_different_namespaces/input/configmap.yaml new file mode 100644 index 000000000..a25762322 --- /dev/null +++ b/rules/workload-mounted-configmap/test/success_different_namespaces/input/configmap.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: myconfigmap + namespace: mynamespace1 +data: + key1: value1 + key2: value2 \ No newline at end of file diff --git a/rules/workload-mounted-configmap/test/success_different_namespaces/input/pod.yaml b/rules/workload-mounted-configmap/test/success_different_namespaces/input/pod.yaml new file mode 100644 index 000000000..eb6ee4dd5 --- /dev/null +++ b/rules/workload-mounted-configmap/test/success_different_namespaces/input/pod.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: Pod +metadata: + name: mypod + namespace: mynamespace +spec: + containers: + - name: mypod + image: redis + volumeMounts: + - name: foo + mountPath: "/etc/foo" + readOnly: true + - name: configvolume + mountPath: "/etc/foo" + volumes: + - name: foo + secret: + secretName: mysecret + optional: true + - name: configvolume + configMap: + name: myconfigmap \ No newline at end of file diff --git a/rules/workload-mounted-configmap/test/success_no_configmap/expected.json b/rules/workload-mounted-configmap/test/success_no_configmap/expected.json new file mode 100644 index 000000000..0637a088a --- /dev/null +++ b/rules/workload-mounted-configmap/test/success_no_configmap/expected.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/rules/workload-mounted-configmap/test/success_no_configmap/input/pod.yaml b/rules/workload-mounted-configmap/test/success_no_configmap/input/pod.yaml new file mode 100644 index 000000000..ec5b3ddf3 --- /dev/null +++ b/rules/workload-mounted-configmap/test/success_no_configmap/input/pod.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Pod +metadata: + name: mypod + namespace: default +spec: + containers: + - name: mypod + image: redis + volumeMounts: + - name: foo + mountPath: "/etc/foo" + readOnly: true + volumes: + - name: foo + secret: + secretName: mysecret + optional: true \ No newline at end of file diff --git a/rules/workload-mounted-pvc/raw.rego b/rules/workload-mounted-pvc/raw.rego new file mode 100644 index 000000000..904c5d25d --- /dev/null +++ b/rules/workload-mounted-pvc/raw.rego @@ -0,0 +1,94 @@ +package armo_builtins + +deny[msga] { + resource := input[_] + volumes_path := get_volumes_path(resource) + volumes := object.get(resource, volumes_path, []) + volume := volumes[i] + volume.persistentVolumeClaim + + PVC := input[_] + PVC.kind == "PersistentVolumeClaim" + PVC.metadata.name == volume.persistentVolumeClaim.claimName + is_same_namespace(PVC.metadata, resource.metadata) + + containers_path := get_containers_path(resource) + containers := object.get(resource, containers_path, []) + container := containers[j] + container.volumeMounts + + # check if volume is mounted + container.volumeMounts[_].name == volume.name + + failedPaths := sprintf("%s[%d].volumeMounts", [concat(".", containers_path), j]) + + msga := { + "alertMessage": sprintf("%v: %v has mounted PVC", [resource.kind, resource.metadata.name]), + "packagename": "armo_builtins", + "failedPaths": [failedPaths], + "fixPaths":[], + "alertObject": { + "k8sApiObjects": [resource] +} + } +} + + +# get_containers_path - get resource containers paths for {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} +get_containers_path(resource) := result { + resource_kinds := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} + resource_kinds[resource.kind] + result = ["spec", "template", "spec", "containers"] +} + +# get_containers_path - get resource containers paths for "Pod" +get_containers_path(resource) := result { + resource.kind == "Pod" + result = ["spec", "containers"] +} + +# get_containers_path - get resource containers paths for "CronJob" +get_containers_path(resource) := result { + resource.kind == "CronJob" + result = ["spec", "jobTemplate", "spec", "template", "spec", "containers"] +} + +# get_volume_path - get resource volumes paths for {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} +get_volumes_path(resource) := result { + resource_kinds := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} + resource_kinds[resource.kind] + result = ["spec", "template", "spec", "volumes"] +} + +# get_volumes_path - get resource volumes paths for "Pod" +get_volumes_path(resource) := result { + resource.kind == "Pod" + result = ["spec", "volumes"] +} + +# get_volumes_path - get resource volumes paths for "CronJob" +get_volumes_path(resource) := result { + resource.kind == "CronJob" + result = ["spec", "jobTemplate", "spec", "template", "spec", "volumes"] +} + + + +is_same_namespace(metadata1, metadata2) { + metadata1.namespace == metadata2.namespace +} + +is_same_namespace(metadata1, metadata2) { + not metadata1.namespace + not metadata2.namespace +} + +is_same_namespace(metadata1, metadata2) { + not metadata2.namespace + metadata1.namespace == "default" +} + +is_same_namespace(metadata1, metadata2) { + not metadata1.namespace + metadata2.namespace == "default" +} \ No newline at end of file diff --git a/rules/workload-mounted-pvc/rule.metadata.json b/rules/workload-mounted-pvc/rule.metadata.json new file mode 100644 index 000000000..dc22b0543 --- /dev/null +++ b/rules/workload-mounted-pvc/rule.metadata.json @@ -0,0 +1,50 @@ +{ + "name": "workload-mounted-pvc", + "attributes": { + "armoBuiltin": true + }, + "ruleLanguage": "Rego", + "match": [ + { + "apiGroups": [ + "" + ], + "apiVersions": [ + "v1" + ], + "resources": [ + "Pod", + "ConfigMap" + ] + }, + { + "apiGroups": [ + "apps" + ], + "apiVersions": [ + "v1" + ], + "resources": [ + "Deployment", + "ReplicaSet", + "DaemonSet", + "StatefulSet" + ] + }, + { + "apiGroups": [ + "batch" + ], + "apiVersions": [ + "*" + ], + "resources": [ + "Job", + "CronJob" + ] + } + ], + "description": "fails if workload mounts PVC", + "remediation": "", + "ruleQuery": "armo_builtins" +} \ No newline at end of file diff --git a/rules/workload-mounted-pvc/test/failed_pod_mounted/expected.json b/rules/workload-mounted-pvc/test/failed_pod_mounted/expected.json new file mode 100644 index 000000000..eefbd7016 --- /dev/null +++ b/rules/workload-mounted-pvc/test/failed_pod_mounted/expected.json @@ -0,0 +1,24 @@ +[ + { + "alertMessage": "Pod: mypod has mounted PVC", + "failedPaths": [ + "spec.containers[0].volumeMounts" + ], + "fixPaths": [], + "ruleStatus": "", + "packagename": "armo_builtins", + "alertScore": 0, + "alertObject": { + "k8sApiObjects": [ + { + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "name": "mypod" + } + } + ] + + } + } +] \ No newline at end of file diff --git a/rules/workload-mounted-pvc/test/failed_pod_mounted/input/PVC.yaml b/rules/workload-mounted-pvc/test/failed_pod_mounted/input/PVC.yaml new file mode 100644 index 000000000..6993c5d8e --- /dev/null +++ b/rules/workload-mounted-pvc/test/failed_pod_mounted/input/PVC.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: myclaim +spec: + accessModes: + - ReadWriteOnce + volumeMode: Filesystem + resources: + requests: + storage: 8Gi + storageClassName: slow + selector: + matchLabels: + release: "stable" + matchExpressions: + - {key: environment, operator: In, values: [dev]} \ No newline at end of file diff --git a/rules/workload-mounted-pvc/test/failed_pod_mounted/input/pod.yaml b/rules/workload-mounted-pvc/test/failed_pod_mounted/input/pod.yaml new file mode 100644 index 000000000..6a6bada6a --- /dev/null +++ b/rules/workload-mounted-pvc/test/failed_pod_mounted/input/pod.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: mypod +spec: + containers: + - name: myfrontend + image: nginx + volumeMounts: + - mountPath: "/var/www/html" + name: mypd + volumes: + - name: mypd + persistentVolumeClaim: + claimName: myclaim \ No newline at end of file diff --git a/rules/workload-mounted-pvc/test/success_different_namespaces/expected.json b/rules/workload-mounted-pvc/test/success_different_namespaces/expected.json new file mode 100644 index 000000000..0637a088a --- /dev/null +++ b/rules/workload-mounted-pvc/test/success_different_namespaces/expected.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/rules/workload-mounted-pvc/test/success_different_namespaces/input/PVC.yaml b/rules/workload-mounted-pvc/test/success_different_namespaces/input/PVC.yaml new file mode 100644 index 000000000..6993c5d8e --- /dev/null +++ b/rules/workload-mounted-pvc/test/success_different_namespaces/input/PVC.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: myclaim +spec: + accessModes: + - ReadWriteOnce + volumeMode: Filesystem + resources: + requests: + storage: 8Gi + storageClassName: slow + selector: + matchLabels: + release: "stable" + matchExpressions: + - {key: environment, operator: In, values: [dev]} \ No newline at end of file diff --git a/rules/workload-mounted-pvc/test/success_different_namespaces/input/pod.yaml b/rules/workload-mounted-pvc/test/success_different_namespaces/input/pod.yaml new file mode 100644 index 000000000..eaabde538 --- /dev/null +++ b/rules/workload-mounted-pvc/test/success_different_namespaces/input/pod.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + name: mypod + namespace: namespace1 +spec: + containers: + - name: myfrontend + image: nginx + volumeMounts: + - mountPath: "/var/www/html" + name: mypd + volumes: + - name: mypd + persistentVolumeClaim: + claimName: myclaim \ No newline at end of file diff --git a/rules/workload-mounted-pvc/test/success_no_PVC/expected.json b/rules/workload-mounted-pvc/test/success_no_PVC/expected.json new file mode 100644 index 000000000..0637a088a --- /dev/null +++ b/rules/workload-mounted-pvc/test/success_no_PVC/expected.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/rules/workload-mounted-pvc/test/success_no_PVC/input/pod.yaml b/rules/workload-mounted-pvc/test/success_no_PVC/input/pod.yaml new file mode 100644 index 000000000..ec5b3ddf3 --- /dev/null +++ b/rules/workload-mounted-pvc/test/success_no_PVC/input/pod.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Pod +metadata: + name: mypod + namespace: default +spec: + containers: + - name: mypod + image: redis + volumeMounts: + - name: foo + mountPath: "/etc/foo" + readOnly: true + volumes: + - name: foo + secret: + secretName: mysecret + optional: true \ No newline at end of file diff --git a/rules/workload-mounted-pvc/test/success_with_PVC_not_mounted/expected.json b/rules/workload-mounted-pvc/test/success_with_PVC_not_mounted/expected.json new file mode 100644 index 000000000..0637a088a --- /dev/null +++ b/rules/workload-mounted-pvc/test/success_with_PVC_not_mounted/expected.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/rules/workload-mounted-pvc/test/success_with_PVC_not_mounted/input/PVC.yaml b/rules/workload-mounted-pvc/test/success_with_PVC_not_mounted/input/PVC.yaml new file mode 100644 index 000000000..6993c5d8e --- /dev/null +++ b/rules/workload-mounted-pvc/test/success_with_PVC_not_mounted/input/PVC.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: myclaim +spec: + accessModes: + - ReadWriteOnce + volumeMode: Filesystem + resources: + requests: + storage: 8Gi + storageClassName: slow + selector: + matchLabels: + release: "stable" + matchExpressions: + - {key: environment, operator: In, values: [dev]} \ No newline at end of file diff --git a/rules/workload-mounted-pvc/test/success_with_PVC_not_mounted/input/pod.yaml b/rules/workload-mounted-pvc/test/success_with_PVC_not_mounted/input/pod.yaml new file mode 100644 index 000000000..42a1ebb24 --- /dev/null +++ b/rules/workload-mounted-pvc/test/success_with_PVC_not_mounted/input/pod.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: mypod +spec: + containers: + - name: myfrontend + image: nginx + volumeMounts: + - mountPath: "/var/www/html" + name: mypd1 + volumes: + - name: mypd + persistentVolumeClaim: + claimName: myclaim \ No newline at end of file From d53a22bbee85fef9864503e7af8fb36b2193af09 Mon Sep 17 00:00:00 2001 From: kooomix Date: Thu, 29 Jun 2023 09:07:16 +0300 Subject: [PATCH 32/48] merge Signed-off-by: kooomix --- controls/C-0257-pvcaccess.json | 10 ++--- controls/C-0258-configmapaccess.json | 12 +++--- frameworks/security.json | 12 ++++++ .../input/rolebinding.yaml | 6 ++- testrunner/go.mod | 3 ++ testrunner/go.sum | 4 ++ testrunner/opaprocessor/processorutils.go | 40 +++++++++++++++++++ 7 files changed, 75 insertions(+), 12 deletions(-) diff --git a/controls/C-0257-pvcaccess.json b/controls/C-0257-pvcaccess.json index 99a0bac53..d2ee83a1b 100644 --- a/controls/C-0257-pvcaccess.json +++ b/controls/C-0257-pvcaccess.json @@ -1,5 +1,5 @@ { - "name": "PVC access", + "name": "Workload with PVC access", "attributes": { "armoBuiltin": true, "controlTypeTags": [ @@ -14,10 +14,10 @@ } ] }, - "description": "", - "remediation": "", - "rulesNames": [], - "test": "", + "description": "This control detects workloads that have mounted PVC. Workloads with PVC access can potentially expose sensitive information and elevate the risk of unauthorized access to critical resources.", + "remediation": "Review the workloads identified by this control and assess whether it's necessary to mount these PVCs. Remove PVC access from workloads that don't require it or ensure appropriate access controls are in place to protect sensitive information.", + "rulesNames": ["workload-mounted-pvc"], + "test": "Check if any workload has mounted PVCs by inspecting their specifications and verifying if PVC volumes are defined", "controlID": "C-0257", "baseScore": 4.0 } \ No newline at end of file diff --git a/controls/C-0258-configmapaccess.json b/controls/C-0258-configmapaccess.json index 4c857b17f..cf0e62870 100644 --- a/controls/C-0258-configmapaccess.json +++ b/controls/C-0258-configmapaccess.json @@ -1,5 +1,5 @@ { - "name": "ConfigMap access", + "name": "Workload with ConfigMap access", "attributes": { "armoBuiltin": true, "controlTypeTags": [ @@ -14,10 +14,10 @@ } ] }, - "description": "", - "remediation": "", - "rulesNames": [], - "test": "", + "description": "This control detects workloads that have mounted ConfigMaps. Workloads with ConfigMap access can potentially expose sensitive information and elevate the risk of unauthorized access to critical resources.", + "remediation": "Review the workloads identified by this control and assess whether it's necessary to mount these configMaps. Remove configMaps access from workloads that don't require it or ensure appropriate access controls are in place to protect sensitive information.", + "rulesNames": ["workload-mounted-configmap"], + "test": "Check if any workload has mounted secrets by inspecting their specifications and verifying if secret volumes are defined", "controlID": "C-0258", - "baseScore": 4.0 + "baseScore": 5.0 } \ No newline at end of file diff --git a/frameworks/security.json b/frameworks/security.json index 2530abe20..e9141a297 100644 --- a/frameworks/security.json +++ b/frameworks/security.json @@ -14,6 +14,18 @@ "name": "Immutable container filesystem" } }, + { + "controlID": "C-0258", + "patch": { + "name": "Workload with configMap access" + } + }, + { + "controlID": "C-0257", + "patch": { + "name": "Workload with PVC access" + } + }, { "controlID": "C-0255", "patch": { diff --git a/rules/ensure-default-service-accounts-has-only-default-roles/test/passed_rolebinding_one_subject/input/rolebinding.yaml b/rules/ensure-default-service-accounts-has-only-default-roles/test/passed_rolebinding_one_subject/input/rolebinding.yaml index fc3b02ef1..eaeb7e332 100644 --- a/rules/ensure-default-service-accounts-has-only-default-roles/test/passed_rolebinding_one_subject/input/rolebinding.yaml +++ b/rules/ensure-default-service-accounts-has-only-default-roles/test/passed_rolebinding_one_subject/input/rolebinding.yaml @@ -8,4 +8,8 @@ metadata: subjects: - kind: ServiceAccount name: default - namespace: default \ No newline at end of file + namespace: default +roleRef: + kind: ClusterRole + name: test + apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/testrunner/go.mod b/testrunner/go.mod index 7aa706fd3..7fb8d8fef 100644 --- a/testrunner/go.mod +++ b/testrunner/go.mod @@ -12,6 +12,8 @@ require ( gopkg.in/yaml.v3 v3.0.1 ) +require github.com/santhosh-tekuri/jsonschema/v5 v5.1.1 // indirect + require ( cloud.google.com/go v0.102.1 // indirect cloud.google.com/go/compute v1.7.0 // indirect @@ -95,6 +97,7 @@ require ( github.com/tchap/go-patricia/v2 v2.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/yannh/kubeconform v0.6.2 github.com/yashtewari/glob-intersection v0.1.0 // indirect go.opencensus.io v0.23.0 // indirect go.uber.org/atomic v1.7.0 // indirect diff --git a/testrunner/go.sum b/testrunner/go.sum index ef2223980..60d22354e 100644 --- a/testrunner/go.sum +++ b/testrunner/go.sum @@ -438,6 +438,8 @@ github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqn github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/santhosh-tekuri/jsonschema/v5 v5.1.1 h1:lEOLY2vyGIqKWUI9nzsOJRV3mb3WC9dXYORsLEUcoeY= +github.com/santhosh-tekuri/jsonschema/v5 v5.1.1/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= @@ -489,6 +491,8 @@ github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMc github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/yannh/kubeconform v0.6.2 h1:xjUxiCcqTBofTsM3UT6fNb/tKRfqjakNfWvHRa3sGOo= +github.com/yannh/kubeconform v0.6.2/go.mod h1:4E6oaL+lh7KgCG2SaOabeeAFBkyKu5D9ab0OEekGcbs= github.com/yashtewari/glob-intersection v0.1.0 h1:6gJvMYQlTDOL3dMsPF6J0+26vwX9MB8/1q3uAdhmTrg= github.com/yashtewari/glob-intersection v0.1.0/go.mod h1:LK7pIC3piUjovexikBbJ26Yml7g8xa5bsjfx2v1fwok= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/testrunner/opaprocessor/processorutils.go b/testrunner/opaprocessor/processorutils.go index 11f830325..159e4442c 100644 --- a/testrunner/opaprocessor/processorutils.go +++ b/testrunner/opaprocessor/processorutils.go @@ -16,6 +16,8 @@ import ( "github.com/kubescape/opa-utils/resources" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/yannh/kubeconform/pkg/resource" + "github.com/yannh/kubeconform/pkg/validator" "gopkg.in/yaml.v3" ) @@ -42,6 +44,37 @@ func convertYamlToJson(i interface{}) interface{} { return i } +// validateInputResource return an error in case the provided k8s resource is not considered valid. +// It uses packages from kubeconform project in order to validate resources. +func validateInputResource(res []byte) error { + k8sResource := resource.Resource{ + Bytes: res, + } + schemaLocation := []string{} + var val validator.Validator + val, err := validator.New(schemaLocation, + validator.Opts{ + Cache: "", + Debug: false, + SkipTLS: false, + SkipKinds: map[string]struct{}{}, + RejectKinds: map[string]struct{}{}, + KubernetesVersion: "master", + Strict: false, + IgnoreMissingSchemas: true, + }, + ) + if err != nil { + return err + } + + result := val.ValidateResource(k8sResource) + if result.Err != nil { + return result.Err + } + return nil +} + func GetInputRawResources(dir string, policyRule *reporthandling.PolicyRule) ([]map[string]interface{}, error) { var IMetadataResources []workloadinterface.IMetadata @@ -53,6 +86,7 @@ func GetInputRawResources(dir string, policyRule *reporthandling.PolicyRule) ([] if resp == nil { return nil, fmt.Errorf("resource is nil") } + metadataResource := objectsenvelopes.NewObject(resp) // if metadataResource.GetNamespace() == "" { // metadataResource.SetNamespace("default") @@ -86,6 +120,12 @@ func GetMockContentFromFile(filename string) (string, error) { if err != nil { return "", err } + + // validate input resource using kubeconform packages + if err = validateInputResource(mockContent); err != nil { + return "", err + } + var body interface{} if err := yaml.Unmarshal([]byte(mockContent), &body); err != nil { return "", err From b71dd359bd81066d19463a536775dc5b5e8b2f9c Mon Sep 17 00:00:00 2001 From: Alessio Greggi Date: Fri, 23 Jun 2023 17:50:47 +0200 Subject: [PATCH 33/48] feat: add exposure-to-internet rule Signed-off-by: Alessio Greggi --- controls/C-0256-exposuretointernet.json | 12 +-- frameworks/security.json | 10 ++- rules/exposure-to-internet/raw.rego | 80 +++++++++++++++++++ rules/exposure-to-internet/rule.metadata.json | 63 +++++++++++++++ .../test/failed_with_ingress/expected.json | 35 ++++++++ .../failed_with_ingress/input/deployment.yaml | 20 +++++ .../failed_with_ingress/input/ingress.yaml | 13 +++ .../failed_with_ingress/input/service.yaml | 11 +++ .../expected.json | 28 +++++++ .../input/deployment.yaml | 20 +++++ .../input/service.yaml | 17 ++++ .../expected.json | 28 +++++++ .../input/deployment.yaml | 20 +++++ .../input/service.yaml | 10 +++ .../test/success_with_ingress/expected.json | 1 + .../input/deployment.yaml | 20 +++++ .../success_with_ingress/input/ingress.yaml | 13 +++ .../success_with_ingress/input/service.yaml | 11 +++ 18 files changed, 404 insertions(+), 8 deletions(-) create mode 100644 rules/exposure-to-internet/raw.rego create mode 100644 rules/exposure-to-internet/rule.metadata.json create mode 100644 rules/exposure-to-internet/test/failed_with_ingress/expected.json create mode 100644 rules/exposure-to-internet/test/failed_with_ingress/input/deployment.yaml create mode 100644 rules/exposure-to-internet/test/failed_with_ingress/input/ingress.yaml create mode 100644 rules/exposure-to-internet/test/failed_with_ingress/input/service.yaml create mode 100644 rules/exposure-to-internet/test/failed_with_service_loadbalancer/expected.json create mode 100644 rules/exposure-to-internet/test/failed_with_service_loadbalancer/input/deployment.yaml create mode 100644 rules/exposure-to-internet/test/failed_with_service_loadbalancer/input/service.yaml create mode 100644 rules/exposure-to-internet/test/failed_with_service_nodeport/expected.json create mode 100644 rules/exposure-to-internet/test/failed_with_service_nodeport/input/deployment.yaml create mode 100644 rules/exposure-to-internet/test/failed_with_service_nodeport/input/service.yaml create mode 100644 rules/exposure-to-internet/test/success_with_ingress/expected.json create mode 100644 rules/exposure-to-internet/test/success_with_ingress/input/deployment.yaml create mode 100644 rules/exposure-to-internet/test/success_with_ingress/input/ingress.yaml create mode 100644 rules/exposure-to-internet/test/success_with_ingress/input/service.yaml diff --git a/controls/C-0256-exposuretointernet.json b/controls/C-0256-exposuretointernet.json index 4f9e34571..35ebe5a93 100644 --- a/controls/C-0256-exposuretointernet.json +++ b/controls/C-0256-exposuretointernet.json @@ -20,10 +20,10 @@ } ] }, - "description": "", - "remediation": "", - "rulesNames": [], - "test": "", + "description": "This control detect workloads that are exposed on Internet through a Service (NodePort or LoadBalancer) or Ingress. It fails in case it find workloads connected with these resources.", + "remediation": "The user can evaluate its exposed resources and apply relevant changes wherever needed.", + "rulesNames": ["exposure-to-internet"], + "test": "Checks if workloads are exposed through the use of NodePort, LoadBalancer or Ingress", "controlID": "C-0256", - "baseScore": 6.0 -} \ No newline at end of file + "baseScore": 7.0 +} diff --git a/frameworks/security.json b/frameworks/security.json index 3054c5264..e192bfacc 100644 --- a/frameworks/security.json +++ b/frameworks/security.json @@ -14,7 +14,13 @@ "name": "Immutable container filesystem" } }, - { + { + "controlID": "C-0256", + "patch": { + "name": "Exposure to Internet" + } + }, + { "controlID": "C-0259", "patch": { "name": "Workload with credential access" @@ -45,4 +51,4 @@ } } ] -} \ No newline at end of file +} diff --git a/rules/exposure-to-internet/raw.rego b/rules/exposure-to-internet/raw.rego new file mode 100644 index 000000000..e82b6c9a3 --- /dev/null +++ b/rules/exposure-to-internet/raw.rego @@ -0,0 +1,80 @@ +package armo_builtins + +# Checks if NodePort or LoadBalancer is connected to a workload to expose something +deny[msga] { + service := input[_] + service.kind == "Service" + is_unsafe_service(service) + + wl := input[_] + spec_template_spec_patterns := {"Deployment", "ReplicaSet", "DaemonSet", "StatefulSet", "Pod", "Job"} + spec_template_spec_patterns[wl.kind] + not wl_connected_to_service(wl, service) + #result := ["spec.selector.matchLabels"] + + msga := { + "alertMessage": sprintf("workload '%v' is exposed through service '%v'", [wl.metadata.name, service.metadata.name]), + "packagename": "armo_builtins", + "alertScore": 7, + "fixPaths": [], + "failedPaths": [], + "alertObject": { + "k8sApiObjects": [wl, service] + } + } +} + +# Checks if Ingress is connected to a service and a workload to expose something +deny[msga] { + ingress := input[_] + ingress.kind == "Ingress" + + svc := input[_] + svc.kind == "Service" + not is_unsafe_service(svc) + + wl := input[_] + spec_template_spec_patterns := {"Deployment", "ReplicaSet", "DaemonSet", "StatefulSet", "Pod", "Job"} + spec_template_spec_patterns[wl.kind] + wl_connected_to_service(wl, svc) + + result := svc_connected_to_ingress(svc, ingress) + + msga := { + "alertMessage": sprintf("workload '%v' is exposed through ingress '%v'", [wl.metadata.name, ingress.metadata.name]), + "packagename": "armo_builtins", + "failedPaths": [], + "fixPaths": [], + "alertScore": 7, + "alertObject": { + "k8sApiObjects": [wl, svc, ingress] + } + } +} + +# ==================================================================================== + +is_unsafe_service(svc) { + svc.spec.type == "NodePort" +} + +is_unsafe_service(svc) { + svc.spec.type == "LoadBalancer" +} + +wl_connected_to_service(wl, svc) { + count({x | svc.spec.selector[x] == wl.metadata.labels[x]}) == count(svc.spec.selector) +} + +wl_connected_to_service(wl, svc) { + wl.spec.selector.matchLabels == svc.spec.selector +} + +# check if service is connected to ingress +svc_connected_to_ingress(svc, ingress) { + rule := ingress.spec.rules[i] + paths := rule.http.paths[j] + svc.metadata.name == paths.backend.serviceName + #result := ["service.metadata.name", sprintf("ingress.spec.rules[%d].http.paths[%d].backend.serviceName", [i,j])] +} + diff --git a/rules/exposure-to-internet/rule.metadata.json b/rules/exposure-to-internet/rule.metadata.json new file mode 100644 index 000000000..46497eb24 --- /dev/null +++ b/rules/exposure-to-internet/rule.metadata.json @@ -0,0 +1,63 @@ +{ + "name": "exposure-to-internet", + "attributes": { + "armoBuiltin": true + }, + "ruleLanguage": "Rego", + "match": [ + { + "apiGroups": [ + "" + ], + "apiVersions": [ + "v1" + ], + "resources": [ + "Pod", + "Service" + ] + }, + { + "apiGroups": [ + "apps" + ], + "apiVersions": [ + "v1" + ], + "resources": [ + "Deployment", + "ReplicaSet", + "DaemonSet", + "StatefulSet" + ] + }, + { + "apiGroups": [ + "batch" + ], + "apiVersions": [ + "*" + ], + "resources": [ + "Job", + "CronJob" + ] + }, + { + "apiGroups": [ + "extensions", + "networking.k8s.io" + ], + "apiVersions": [ + "v1beta1", + "v1" + ], + "resources": [ + "Ingress" + ] + } + ], + "description": "fails in case the running workload has binded Service or Ingress that are exposing it on Internet.", + "remediation": "", + "ruleQuery": "armo_builtins" +} diff --git a/rules/exposure-to-internet/test/failed_with_ingress/expected.json b/rules/exposure-to-internet/test/failed_with_ingress/expected.json new file mode 100644 index 000000000..e9194e1b1 --- /dev/null +++ b/rules/exposure-to-internet/test/failed_with_ingress/expected.json @@ -0,0 +1,35 @@ +[ + { + "alertMessage": "workload 'my-app' is exposed through ingress 'my-ingress'", + "fixPaths": [], + "failedPaths": [], + "ruleStatus": "", + "packagename": "armo_builtins", + "alertScore": 7, + "alertObject": { + "k8sApiObjects": [ + { + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "name": "my-app" + } + }, + { + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "name": "my-service" + } + }, + { + "apiVersion": "networking.k8s.io/v1beta1", + "kind": "Ingress", + "metadata": { + "name": "my-ingress" + } + } + ] + } + } +] diff --git a/rules/exposure-to-internet/test/failed_with_ingress/input/deployment.yaml b/rules/exposure-to-internet/test/failed_with_ingress/input/deployment.yaml new file mode 100644 index 000000000..c886b6c46 --- /dev/null +++ b/rules/exposure-to-internet/test/failed_with_ingress/input/deployment.yaml @@ -0,0 +1,20 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-app + namespace: default +spec: + selector: + matchLabels: + app: my-app + template: + metadata: + labels: + app: my-app + spec: + containers: + - args: + - server + image: argoproj/argocli:latest + name: argo-server + diff --git a/rules/exposure-to-internet/test/failed_with_ingress/input/ingress.yaml b/rules/exposure-to-internet/test/failed_with_ingress/input/ingress.yaml new file mode 100644 index 000000000..a9b2f0e0b --- /dev/null +++ b/rules/exposure-to-internet/test/failed_with_ingress/input/ingress.yaml @@ -0,0 +1,13 @@ +apiVersion: networking.k8s.io/v1beta1 +kind: Ingress +metadata: + name: my-ingress +spec: + ingressClassName: nginx + rules: + - host: myservicea.foo.org + http: + paths: + - path: / + backend: + serviceName: my-service diff --git a/rules/exposure-to-internet/test/failed_with_ingress/input/service.yaml b/rules/exposure-to-internet/test/failed_with_ingress/input/service.yaml new file mode 100644 index 000000000..7ba441575 --- /dev/null +++ b/rules/exposure-to-internet/test/failed_with_ingress/input/service.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Service +metadata: + name: my-service +spec: + selector: + app: my-app + type: ClusterIP + ports: + - targetPort: 80 + port: 80 diff --git a/rules/exposure-to-internet/test/failed_with_service_loadbalancer/expected.json b/rules/exposure-to-internet/test/failed_with_service_loadbalancer/expected.json new file mode 100644 index 000000000..c282d7264 --- /dev/null +++ b/rules/exposure-to-internet/test/failed_with_service_loadbalancer/expected.json @@ -0,0 +1,28 @@ +[ + { + "alertMessage": "workload 'my-app' is exposed through service 'my-service'", + "fixPaths": [], + "failedPaths": [], + "ruleStatus": "", + "packagename": "armo_builtins", + "alertScore": 7, + "alertObject": { + "k8sApiObjects": [ + { + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "name": "my-app" + } + }, + { + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "name": "my-service" + } + } + ] + } + } +] diff --git a/rules/exposure-to-internet/test/failed_with_service_loadbalancer/input/deployment.yaml b/rules/exposure-to-internet/test/failed_with_service_loadbalancer/input/deployment.yaml new file mode 100644 index 000000000..49a2f5106 --- /dev/null +++ b/rules/exposure-to-internet/test/failed_with_service_loadbalancer/input/deployment.yaml @@ -0,0 +1,20 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-app + namespace: default +spec: + selector: + matchLabels: + app: argo-server + template: + metadata: + labels: + app: argo-server + spec: + containers: + - args: + - server + image: argoproj/argocli:latest + name: argo-server + diff --git a/rules/exposure-to-internet/test/failed_with_service_loadbalancer/input/service.yaml b/rules/exposure-to-internet/test/failed_with_service_loadbalancer/input/service.yaml new file mode 100644 index 000000000..2286113ac --- /dev/null +++ b/rules/exposure-to-internet/test/failed_with_service_loadbalancer/input/service.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: my-service +spec: + selector: + app.kubernetes.io/name: MyApp + ports: + - protocol: TCP + port: 80 + targetPort: 9376 + clusterIP: 10.0.171.239 + type: LoadBalancer +status: + loadBalancer: + ingress: + - ip: 192.0.2.127 diff --git a/rules/exposure-to-internet/test/failed_with_service_nodeport/expected.json b/rules/exposure-to-internet/test/failed_with_service_nodeport/expected.json new file mode 100644 index 000000000..6100000ce --- /dev/null +++ b/rules/exposure-to-internet/test/failed_with_service_nodeport/expected.json @@ -0,0 +1,28 @@ +[ + { + "alertMessage": "workload 'my-app' is exposed through service 'my-service'", + "fixPaths": [], + "failedPaths": [], + "ruleStatus": "", + "packagename": "armo_builtins", + "alertScore": 7, + "alertObject": { + "k8sApiObjects": [ + { + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "name": "my-app" + } + }, + { + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "name": "my-service" + } + } + ] + } + } +] diff --git a/rules/exposure-to-internet/test/failed_with_service_nodeport/input/deployment.yaml b/rules/exposure-to-internet/test/failed_with_service_nodeport/input/deployment.yaml new file mode 100644 index 000000000..49a2f5106 --- /dev/null +++ b/rules/exposure-to-internet/test/failed_with_service_nodeport/input/deployment.yaml @@ -0,0 +1,20 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-app + namespace: default +spec: + selector: + matchLabels: + app: argo-server + template: + metadata: + labels: + app: argo-server + spec: + containers: + - args: + - server + image: argoproj/argocli:latest + name: argo-server + diff --git a/rules/exposure-to-internet/test/failed_with_service_nodeport/input/service.yaml b/rules/exposure-to-internet/test/failed_with_service_nodeport/input/service.yaml new file mode 100644 index 000000000..70999d7b9 --- /dev/null +++ b/rules/exposure-to-internet/test/failed_with_service_nodeport/input/service.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Service +metadata: + name: my-service +spec: + type: NodePort + ports: + - port: 80 + targetPort: 80 + nodePort: 30007 diff --git a/rules/exposure-to-internet/test/success_with_ingress/expected.json b/rules/exposure-to-internet/test/success_with_ingress/expected.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/rules/exposure-to-internet/test/success_with_ingress/expected.json @@ -0,0 +1 @@ +[] diff --git a/rules/exposure-to-internet/test/success_with_ingress/input/deployment.yaml b/rules/exposure-to-internet/test/success_with_ingress/input/deployment.yaml new file mode 100644 index 000000000..c886b6c46 --- /dev/null +++ b/rules/exposure-to-internet/test/success_with_ingress/input/deployment.yaml @@ -0,0 +1,20 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-app + namespace: default +spec: + selector: + matchLabels: + app: my-app + template: + metadata: + labels: + app: my-app + spec: + containers: + - args: + - server + image: argoproj/argocli:latest + name: argo-server + diff --git a/rules/exposure-to-internet/test/success_with_ingress/input/ingress.yaml b/rules/exposure-to-internet/test/success_with_ingress/input/ingress.yaml new file mode 100644 index 000000000..bab67d137 --- /dev/null +++ b/rules/exposure-to-internet/test/success_with_ingress/input/ingress.yaml @@ -0,0 +1,13 @@ +apiVersion: networking.k8s.io/v1beta1 +kind: Ingress +metadata: + name: my-ingress +spec: + ingressClassName: nginx + rules: + - host: myservicea.foo.org + http: + paths: + - path: / + backend: + serviceName: my-service-b diff --git a/rules/exposure-to-internet/test/success_with_ingress/input/service.yaml b/rules/exposure-to-internet/test/success_with_ingress/input/service.yaml new file mode 100644 index 000000000..7ba441575 --- /dev/null +++ b/rules/exposure-to-internet/test/success_with_ingress/input/service.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Service +metadata: + name: my-service +spec: + selector: + app: my-app + type: ClusterIP + ports: + - targetPort: 80 + port: 80 From a70a4740f4b9bf1a5ea3547e408e79e900c52f39 Mon Sep 17 00:00:00 2001 From: Alessio Greggi Date: Fri, 23 Jun 2023 17:51:05 +0200 Subject: [PATCH 34/48] fix(scripts): fix typo Signed-off-by: Alessio Greggi --- scripts/init-rule.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/init-rule.py b/scripts/init-rule.py index 9800f0050..86a0d9480 100644 --- a/scripts/init-rule.py +++ b/scripts/init-rule.py @@ -259,7 +259,7 @@ def define_args(): parser.add_argument('--test-list', type=str, default=test_list_default, - help='comma separated list of tests you want to provide on the rule. example: succes,failed') + help='comma separated list of tests you want to provide on the rule. example: success,failed') args = parser.parse_args() return args From 66a474f0a41e4a3ff67663bb044967498d9c03b6 Mon Sep 17 00:00:00 2001 From: Alessio Greggi Date: Tue, 27 Jun 2023 12:20:50 +0200 Subject: [PATCH 35/48] fix(testrunner): add error description Signed-off-by: Alessio Greggi --- testrunner/opaprocessor/processorutils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testrunner/opaprocessor/processorutils.go b/testrunner/opaprocessor/processorutils.go index 159e4442c..7a63b0f4d 100644 --- a/testrunner/opaprocessor/processorutils.go +++ b/testrunner/opaprocessor/processorutils.go @@ -286,7 +286,7 @@ func RunSingleTest(t *testing.T, dir string, policyRule *reporthandling.PolicyRu expectedResponses, err := GetExpectedResults(dir) if err != nil { - return err + return fmt.Errorf("expected.json doesn't match: %v", err) } err = AssertResponses(t, responses, expectedResponses) From 6e48a5dbd82d2b30c0f0e5f663b2ced2c2f90059 Mon Sep 17 00:00:00 2001 From: Alessio Greggi Date: Tue, 4 Jul 2023 12:16:43 +0200 Subject: [PATCH 36/48] feat: add control serviceaccount-token-mount Signed-off-by: Alessio Greggi --- controls/C-0261-satokenmounted.json | 12 +- frameworks/security.json | 6 + rules/serviceaccount-token-mount/raw.rego | 163 ++++++++++++++++++ .../rule.metadata.json | 64 +++++++ .../test/both-mount-default/expected.json | 1 + .../test/both-mount-default/input/file.yaml | 15 ++ .../input/serviceaccount.json | 16 ++ .../test/both-mount/expected.json | 2 + .../test/both-mount/input/file.yaml | 17 ++ .../test/both-mount/input/sa.json | 17 ++ .../test/pod-mount-and-rb-bind/expected.json | 20 +++ .../pod-mount-and-rb-bind/input/file.yaml | 17 ++ .../input/rolebinding.yaml | 13 ++ .../input/serviceaccount.json | 17 ++ .../test/pod-mount/expected.json | 1 + .../test/pod-mount/input/file.yaml | 16 ++ .../test/pod-mount/input/serviceaccount.json | 17 ++ .../test/sa-mount/expected.json | 1 + .../test/sa-mount/input/file.yaml | 16 ++ .../test/sa-mount/input/serviceaccount.json | 17 ++ 20 files changed, 442 insertions(+), 6 deletions(-) create mode 100644 rules/serviceaccount-token-mount/raw.rego create mode 100644 rules/serviceaccount-token-mount/rule.metadata.json create mode 100644 rules/serviceaccount-token-mount/test/both-mount-default/expected.json create mode 100644 rules/serviceaccount-token-mount/test/both-mount-default/input/file.yaml create mode 100644 rules/serviceaccount-token-mount/test/both-mount-default/input/serviceaccount.json create mode 100644 rules/serviceaccount-token-mount/test/both-mount/expected.json create mode 100644 rules/serviceaccount-token-mount/test/both-mount/input/file.yaml create mode 100644 rules/serviceaccount-token-mount/test/both-mount/input/sa.json create mode 100644 rules/serviceaccount-token-mount/test/pod-mount-and-rb-bind/expected.json create mode 100644 rules/serviceaccount-token-mount/test/pod-mount-and-rb-bind/input/file.yaml create mode 100644 rules/serviceaccount-token-mount/test/pod-mount-and-rb-bind/input/rolebinding.yaml create mode 100644 rules/serviceaccount-token-mount/test/pod-mount-and-rb-bind/input/serviceaccount.json create mode 100644 rules/serviceaccount-token-mount/test/pod-mount/expected.json create mode 100644 rules/serviceaccount-token-mount/test/pod-mount/input/file.yaml create mode 100644 rules/serviceaccount-token-mount/test/pod-mount/input/serviceaccount.json create mode 100644 rules/serviceaccount-token-mount/test/sa-mount/expected.json create mode 100644 rules/serviceaccount-token-mount/test/sa-mount/input/file.yaml create mode 100644 rules/serviceaccount-token-mount/test/sa-mount/input/serviceaccount.json diff --git a/controls/C-0261-satokenmounted.json b/controls/C-0261-satokenmounted.json index aa7f667c7..4590c9ba3 100644 --- a/controls/C-0261-satokenmounted.json +++ b/controls/C-0261-satokenmounted.json @@ -1,5 +1,5 @@ { - "name": "SA token mounted", + "name": "ServiceAccount token mounted", "attributes": { "armoBuiltin": true, "controlTypeTags": [ @@ -14,10 +14,10 @@ } ] }, - "description": "", + "description": "Potential attacker may gain access to a workload and steal its ServiceAccount token. Therefore, it is recommended to disable automatic mapping of the ServiceAccount tokens in ServiceAccount configuration, enable it only for workloads that need to use them and ensure that these ServiceAccount is not bound with a ClusterRoleBinding or a RoleBinding.", "remediation": "", - "rulesNames": [], - "test": "", + "rulesNames": ["automount-service-account"], + "test": "test if ServiceAccount token is mounted on workload and it has at least one binding.", "controlID": "C-0261", - "baseScore": 6.0 -} \ No newline at end of file + "baseScore": 7.0 +} diff --git a/frameworks/security.json b/frameworks/security.json index e192bfacc..7d465be32 100644 --- a/frameworks/security.json +++ b/frameworks/security.json @@ -44,6 +44,12 @@ "name": "Missing network policy" } }, + { + "controlID": "C-0261", + "patch": { + "name": "ServiceAccount token mounted" + } + }, { "controlID": "C-0255", "patch": { diff --git a/rules/serviceaccount-token-mount/raw.rego b/rules/serviceaccount-token-mount/raw.rego new file mode 100644 index 000000000..bf905d954 --- /dev/null +++ b/rules/serviceaccount-token-mount/raw.rego @@ -0,0 +1,163 @@ +package armo_builtins + +# -- ---- For workloads -- ---- +# Fails if pod mount tokens by default (either by its config or by its SA config) + + # POD +deny [msga]{ + pod := input[_] + pod.kind == "Pod" + + beggining_of_path := "spec." + wl_namespace := pod.metadata.namespace + result := is_sa_auto_mounted(pod.spec, beggining_of_path, wl_namespace) + failed_path := get_failed_path(result) + fixed_path := get_fixed_path(result) + + msga := { + "alertMessage": sprintf("Pod: %v in the following namespace: %v mounts service account tokens by default", [pod.metadata.name, pod.metadata.namespace]), + "alertScore": 9, + "packagename": "armo_builtins", + "fixPaths": fixed_path, + "failedPaths": failed_path, + "alertObject": { + "k8sApiObjects": [pod] + } + } +} + +# WORKLOADS +deny[msga] { + wl := input[_] + spec_template_spec_patterns := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} + spec_template_spec_patterns[wl.kind] + beggining_of_path := "spec.template.spec." + + wl_namespace := wl.metadata.namespace + result := is_sa_auto_mounted(wl.spec.template.spec, beggining_of_path, wl_namespace) + failed_path := get_failed_path(result) + fixed_path := get_fixed_path(result) + + msga := { + "alertMessage": sprintf("%v: %v in the following namespace: %v mounts service account tokens by default", [wl.kind, wl.metadata.name, wl.metadata.namespace]), + "packagename": "armo_builtins", + "alertScore": 7, + "fixPaths": fixed_path, + "failedPaths": failed_path, + "alertObject": { + "k8sApiObjects": [wl] + } + } +} + +# CRONJOB +deny[msga] { + wl := input[_] + wl.kind == "CronJob" + container = wl.spec.jobTemplate.spec.template.spec.containers[i] + beggining_of_path := "spec.jobTemplate.spec.template.spec." + + wl_namespace := wl.metadata.namespace + result := is_sa_auto_mounted(wl.spec.jobTemplate.spec.template.spec, beggining_of_path, wl_namespace) + failed_path := get_failed_path(result) + fixed_path := get_fixed_path(result) + + msga := { + "alertMessage": sprintf("%v: %v in the following namespace: %v mounts service account tokens by default", [wl.kind, wl.metadata.name, wl.metadata.namespace]), + "packagename": "armo_builtins", + "alertScore": 7, + "fixPaths": fixed_path, + "failedPaths": failed_path, + "alertObject": { + "k8sApiObjects": [wl] + } + } +} + + # -- ---- For workloads -- ---- +is_sa_auto_mounted(spec, beggining_of_path, wl_namespace) = [failed_path, fix_path] { + # automountServiceAccountToken not in pod spec + not spec.automountServiceAccountToken == false + not spec.automountServiceAccountToken == true + + # check if SA automount by default + sa := input[_] + is_same_sa(spec, sa.metadata.name) + is_same_namespace(sa.metadata.namespace , wl_namespace) + has_service_account_binding(sa) + + # path is pod spec + fix_path = { "path": sprintf("%vautomountServiceAccountToken", [beggining_of_path]), "value": "false"} + failed_path = "" +} + +get_failed_path(paths) = [paths[0]] { + paths[0] != "" +} else = [] + + +get_fixed_path(paths) = [paths[1]] { + paths[1] != "" +} else = [] + +is_sa_auto_mounted(spec, beggining_of_path, wl_namespace) = [failed_path, fix_path] { + # automountServiceAccountToken set to true in pod spec + spec.automountServiceAccountToken == true + + # SA automount by default + service_accounts := [service_account | service_account = input[_]; service_account.kind == "ServiceAccount"] + count(service_accounts) > 0 + sa := service_accounts[_] + is_same_sa(spec, sa.metadata.name) + is_same_namespace(sa.metadata.namespace , wl_namespace) + has_service_account_binding(sa) + + failed_path = sprintf("%vautomountServiceAccountToken", [beggining_of_path]) + fix_path = "" +} + +is_same_sa(spec, serviceAccountName) { + spec.serviceAccountName == serviceAccountName +} + +is_same_sa(spec, serviceAccountName) { + not spec.serviceAccountName + serviceAccountName == "default" +} + +is_same_namespace(metadata1, metadata2) { + metadata1.namespace == metadata2.namespace +} + +is_same_namespace(metadata1, metadata2) { + not metadata1.namespace + not metadata2.namespace +} + +is_same_namespace(metadata1, metadata2) { + not metadata2.namespace + metadata1.namespace == "default" +} + +is_same_namespace(metadata1, metadata2) { + not metadata1.namespace + metadata2.namespace == "default" +} + +# checks if RoleBinding has a bind with the given ServiceAccount +has_service_account_binding(service_account) { + role_bindings := [role_binding | role_binding = input[_]; role_binding.kind == "RoleBinding"] + role_binding := role_bindings[_] + role_binding.subjects[_].name == service_account.metadata.name + role_binding.subjects[_].namespace == service_account.metadata.namespace + role_binding.subjects[_].kind == "ServiceAccount" +} + +# checks if ClusterRoleBinding has a bind with the given ServiceAccount +has_service_account_binding(service_account) { + cluster_role_bindings := [cluster_role_binding | cluster_role_binding = input[_]; cluster_role_binding.kind == "ClusterRoleBinding"] + cluster_role_binding := cluster_role_bindings[_] + cluster_role_binding.subjects[_].name == service_account.metadata.name + cluster_role_binding.subjects[_].namespace == service_account.metadata.namespace + cluster_role_binding.subjects[_].kind == "ServiceAccount" +} diff --git a/rules/serviceaccount-token-mount/rule.metadata.json b/rules/serviceaccount-token-mount/rule.metadata.json new file mode 100644 index 000000000..b62fd3678 --- /dev/null +++ b/rules/serviceaccount-token-mount/rule.metadata.json @@ -0,0 +1,64 @@ +{ + "name": "automount-service-account", + "attributes": { + "armoBuiltin": true + }, + "ruleLanguage": "Rego", + "match": [ + { + "apiGroups": [ + "" + ], + "apiVersions": [ + "v1" + ], + "resources": [ + "Pod", + "ServiceAccount" + ] + }, + { + "apiGroups": [ + "rbac.authorization.k8s.io" + ], + "apiVersions": [ + "v1" + ], + "resources": [ + "RoleBinding", + "ClusterRoleBinding" + ] + }, + { + "apiGroups": [ + "apps" + ], + "apiVersions": [ + "v1" + ], + "resources": [ + "Deployment", + "ReplicaSet", + "DaemonSet", + "StatefulSet" + ] + }, + { + "apiGroups": [ + "batch" + ], + "apiVersions": [ + "*" + ], + "resources": [ + "Job", + "CronJob" + ] + } + ], + "ruleDependencies": [ + ], + "description": "fails if service account and workloads mount service account token by default", + "remediation": "Make sure that the automountServiceAccountToken field on the service account spec if set to false", + "ruleQuery": "armo_builtins" +} diff --git a/rules/serviceaccount-token-mount/test/both-mount-default/expected.json b/rules/serviceaccount-token-mount/test/both-mount-default/expected.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/rules/serviceaccount-token-mount/test/both-mount-default/expected.json @@ -0,0 +1 @@ +[] diff --git a/rules/serviceaccount-token-mount/test/both-mount-default/input/file.yaml b/rules/serviceaccount-token-mount/test/both-mount-default/input/file.yaml new file mode 100644 index 000000000..d9bad8b02 --- /dev/null +++ b/rules/serviceaccount-token-mount/test/both-mount-default/input/file.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test-pd +spec: + containers: + - image: k8s.gcr.io/test-webserver + name: test-container + volumeMounts: + - mountPath: /test-pd + name: test-volume + volumes: + - name: test-volume + hostPath: + path: /var diff --git a/rules/serviceaccount-token-mount/test/both-mount-default/input/serviceaccount.json b/rules/serviceaccount-token-mount/test/both-mount-default/input/serviceaccount.json new file mode 100644 index 000000000..365b25c6d --- /dev/null +++ b/rules/serviceaccount-token-mount/test/both-mount-default/input/serviceaccount.json @@ -0,0 +1,16 @@ +{ + "apiVersion": "v1", + "kind": "ServiceAccount", + "metadata": { + "creationTimestamp": "2022-02-07T11:21:55Z", + "name": "default", + "namespace": "default", + "resourceVersion": "410", + "uid": "5195ed3a-fa3c-46ce-8c66-32d1a83ea41f" + }, + "secrets": [ + { + "name": "default-token-sn9f8" + } + ] +} diff --git a/rules/serviceaccount-token-mount/test/both-mount/expected.json b/rules/serviceaccount-token-mount/test/both-mount/expected.json new file mode 100644 index 000000000..0d4f101c7 --- /dev/null +++ b/rules/serviceaccount-token-mount/test/both-mount/expected.json @@ -0,0 +1,2 @@ +[ +] diff --git a/rules/serviceaccount-token-mount/test/both-mount/input/file.yaml b/rules/serviceaccount-token-mount/test/both-mount/input/file.yaml new file mode 100644 index 000000000..495720efa --- /dev/null +++ b/rules/serviceaccount-token-mount/test/both-mount/input/file.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test-pd + namespace: default +spec: + automountServiceAccountToken: true + containers: + - image: k8s.gcr.io/test-webserver + name: test-container + volumeMounts: + - mountPath: /test-pd + name: test-volume + volumes: + - name: test-volume + hostPath: + path: /var diff --git a/rules/serviceaccount-token-mount/test/both-mount/input/sa.json b/rules/serviceaccount-token-mount/test/both-mount/input/sa.json new file mode 100644 index 000000000..ab36c3bb1 --- /dev/null +++ b/rules/serviceaccount-token-mount/test/both-mount/input/sa.json @@ -0,0 +1,17 @@ +{ + "apiVersion": "v1", + "kind": "ServiceAccount", + "automountServiceAccountToken": true, + "metadata": { + "creationTimestamp": "2022-02-07T11:21:55Z", + "name": "default", + "namespace": "default", + "resourceVersion": "410", + "uid": "5195ed3a-fa3c-46ce-8c66-32d1a83ea41f" + }, + "secrets": [ + { + "name": "default-token-sn9f8" + } + ] +} diff --git a/rules/serviceaccount-token-mount/test/pod-mount-and-rb-bind/expected.json b/rules/serviceaccount-token-mount/test/pod-mount-and-rb-bind/expected.json new file mode 100644 index 000000000..60d95519a --- /dev/null +++ b/rules/serviceaccount-token-mount/test/pod-mount-and-rb-bind/expected.json @@ -0,0 +1,20 @@ +[ + { + "alertMessage": "Pod: test-pd in the following namespace: default mounts service account tokens by default", + "alertScore": 9, + "packagename": "armo_builtins", + "fixPaths": [], + "failedPaths": ["spec.automountServiceAccountToken"], + "alertObject": { + "k8sApiObjects": [ + { + "apiVersion":"v1", + "kind":"Pod", + "metadata":{ + "name":"test-pd" + } + } + ] + } + } +] diff --git a/rules/serviceaccount-token-mount/test/pod-mount-and-rb-bind/input/file.yaml b/rules/serviceaccount-token-mount/test/pod-mount-and-rb-bind/input/file.yaml new file mode 100644 index 000000000..495720efa --- /dev/null +++ b/rules/serviceaccount-token-mount/test/pod-mount-and-rb-bind/input/file.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test-pd + namespace: default +spec: + automountServiceAccountToken: true + containers: + - image: k8s.gcr.io/test-webserver + name: test-container + volumeMounts: + - mountPath: /test-pd + name: test-volume + volumes: + - name: test-volume + hostPath: + path: /var diff --git a/rules/serviceaccount-token-mount/test/pod-mount-and-rb-bind/input/rolebinding.yaml b/rules/serviceaccount-token-mount/test/pod-mount-and-rb-bind/input/rolebinding.yaml new file mode 100644 index 000000000..5eebb29f3 --- /dev/null +++ b/rules/serviceaccount-token-mount/test/pod-mount-and-rb-bind/input/rolebinding.yaml @@ -0,0 +1,13 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: my-role-binding + namespace: default +subjects: +- kind: ServiceAccount + name: default + namespace: default +roleRef: + kind: Role + name: my-role + apiGroup: rbac.authorization.k8s.io diff --git a/rules/serviceaccount-token-mount/test/pod-mount-and-rb-bind/input/serviceaccount.json b/rules/serviceaccount-token-mount/test/pod-mount-and-rb-bind/input/serviceaccount.json new file mode 100644 index 000000000..dd44d7488 --- /dev/null +++ b/rules/serviceaccount-token-mount/test/pod-mount-and-rb-bind/input/serviceaccount.json @@ -0,0 +1,17 @@ +{ + "apiVersion": "v1", + "kind": "ServiceAccount", + "automountServiceAccountToken": false, + "metadata": { + "creationTimestamp": "2022-02-07T11:21:55Z", + "name": "default", + "namespace": "default", + "resourceVersion": "410", + "uid": "5195ed3a-fa3c-46ce-8c66-32d1a83ea41f" + }, + "secrets": [ + { + "name": "default-token-sn9f8" + } + ] +} diff --git a/rules/serviceaccount-token-mount/test/pod-mount/expected.json b/rules/serviceaccount-token-mount/test/pod-mount/expected.json new file mode 100644 index 000000000..0637a088a --- /dev/null +++ b/rules/serviceaccount-token-mount/test/pod-mount/expected.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/rules/serviceaccount-token-mount/test/pod-mount/input/file.yaml b/rules/serviceaccount-token-mount/test/pod-mount/input/file.yaml new file mode 100644 index 000000000..2710c772a --- /dev/null +++ b/rules/serviceaccount-token-mount/test/pod-mount/input/file.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test-pd +spec: + automountServiceAccountToken: true + containers: + - image: k8s.gcr.io/test-webserver + name: test-container + volumeMounts: + - mountPath: /test-pd + name: test-volume + volumes: + - name: test-volume + hostPath: + path: /var diff --git a/rules/serviceaccount-token-mount/test/pod-mount/input/serviceaccount.json b/rules/serviceaccount-token-mount/test/pod-mount/input/serviceaccount.json new file mode 100644 index 000000000..dd44d7488 --- /dev/null +++ b/rules/serviceaccount-token-mount/test/pod-mount/input/serviceaccount.json @@ -0,0 +1,17 @@ +{ + "apiVersion": "v1", + "kind": "ServiceAccount", + "automountServiceAccountToken": false, + "metadata": { + "creationTimestamp": "2022-02-07T11:21:55Z", + "name": "default", + "namespace": "default", + "resourceVersion": "410", + "uid": "5195ed3a-fa3c-46ce-8c66-32d1a83ea41f" + }, + "secrets": [ + { + "name": "default-token-sn9f8" + } + ] +} diff --git a/rules/serviceaccount-token-mount/test/sa-mount/expected.json b/rules/serviceaccount-token-mount/test/sa-mount/expected.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/rules/serviceaccount-token-mount/test/sa-mount/expected.json @@ -0,0 +1 @@ +[] diff --git a/rules/serviceaccount-token-mount/test/sa-mount/input/file.yaml b/rules/serviceaccount-token-mount/test/sa-mount/input/file.yaml new file mode 100644 index 000000000..cbeb4dbeb --- /dev/null +++ b/rules/serviceaccount-token-mount/test/sa-mount/input/file.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test-pd +spec: + automountServiceAccountToken: false + containers: + - image: k8s.gcr.io/test-webserver + name: test-container + volumeMounts: + - mountPath: /test-pd + name: test-volume + volumes: + - name: test-volume + hostPath: + path: /var diff --git a/rules/serviceaccount-token-mount/test/sa-mount/input/serviceaccount.json b/rules/serviceaccount-token-mount/test/sa-mount/input/serviceaccount.json new file mode 100644 index 000000000..ab36c3bb1 --- /dev/null +++ b/rules/serviceaccount-token-mount/test/sa-mount/input/serviceaccount.json @@ -0,0 +1,17 @@ +{ + "apiVersion": "v1", + "kind": "ServiceAccount", + "automountServiceAccountToken": true, + "metadata": { + "creationTimestamp": "2022-02-07T11:21:55Z", + "name": "default", + "namespace": "default", + "resourceVersion": "410", + "uid": "5195ed3a-fa3c-46ce-8c66-32d1a83ea41f" + }, + "secrets": [ + { + "name": "default-token-sn9f8" + } + ] +} From 7746c93c2175595859af141616d6fdbd927768b1 Mon Sep 17 00:00:00 2001 From: Alessio Greggi Date: Thu, 6 Jul 2023 08:55:44 +0200 Subject: [PATCH 37/48] fix(controls): add remediation for C-0261 Co-authored-by: YiscahLevySilas1 <80635572+YiscahLevySilas1@users.noreply.github.com> --- controls/C-0261-satokenmounted.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/controls/C-0261-satokenmounted.json b/controls/C-0261-satokenmounted.json index 4590c9ba3..f57ad3ef7 100644 --- a/controls/C-0261-satokenmounted.json +++ b/controls/C-0261-satokenmounted.json @@ -14,8 +14,8 @@ } ] }, - "description": "Potential attacker may gain access to a workload and steal its ServiceAccount token. Therefore, it is recommended to disable automatic mapping of the ServiceAccount tokens in ServiceAccount configuration, enable it only for workloads that need to use them and ensure that these ServiceAccount is not bound with a ClusterRoleBinding or a RoleBinding.", - "remediation": "", + "description": "Potential attacker may gain access to a workload and steal its ServiceAccount token. Therefore, it is recommended to disable automatic mapping of the ServiceAccount tokens in ServiceAccount configuration. Enable it only for workloads that need to use them and ensure that this ServiceAccount is not bound to an unnecessary ClusterRoleBinding or RoleBinding.", + "remediation": "Disable automatic mounting of service account tokens to pods at the workload level, by specifying automountServiceAccountToken: false. Enable it only for workloads that need to use them and ensure that this ServiceAccount doesn't have unnecessary permissions", "rulesNames": ["automount-service-account"], "test": "test if ServiceAccount token is mounted on workload and it has at least one binding.", "controlID": "C-0261", From 6f006883b2ac9ca897e6ad9158990cd0fe03df41 Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Sun, 9 Jul 2023 12:02:11 +0300 Subject: [PATCH 38/48] fix rule + add related objects Signed-off-by: YiscahLevySilas1 --- rules/exposure-to-internet/raw.rego | 25 ++++++---- .../test/failed_with_ingress/expected.json | 49 +++++++++++++------ .../expected.json | 47 +++++++++++++++--- .../input/service.yaml | 4 +- .../expected.json | 39 +++++++++++---- .../input/service.yaml | 2 + 6 files changed, 123 insertions(+), 43 deletions(-) diff --git a/rules/exposure-to-internet/raw.rego b/rules/exposure-to-internet/raw.rego index e82b6c9a3..37f7077b3 100644 --- a/rules/exposure-to-internet/raw.rego +++ b/rules/exposure-to-internet/raw.rego @@ -9,9 +9,8 @@ deny[msga] { wl := input[_] spec_template_spec_patterns := {"Deployment", "ReplicaSet", "DaemonSet", "StatefulSet", "Pod", "Job"} spec_template_spec_patterns[wl.kind] - not wl_connected_to_service(wl, service) - #result := ["spec.selector.matchLabels"] - + wl_connected_to_service(wl, service) + failPath := ["spec.type"] msga := { "alertMessage": sprintf("workload '%v' is exposed through service '%v'", [wl.metadata.name, service.metadata.name]), "packagename": "armo_builtins", @@ -19,8 +18,12 @@ deny[msga] { "fixPaths": [], "failedPaths": [], "alertObject": { - "k8sApiObjects": [wl, service] - } + "k8sApiObjects": [wl] + }, + "relatedObjects": [{ + "object": service, + "failedPaths": failPath, + }] } } @@ -47,8 +50,12 @@ deny[msga] { "fixPaths": [], "alertScore": 7, "alertObject": { - "k8sApiObjects": [wl, svc, ingress] - } + "k8sApiObjects": [wl] + }, + "relatedObjects": [{ + "object": ingress, + "failedPaths": result, + }] } } @@ -71,10 +78,10 @@ wl_connected_to_service(wl, svc) { } # check if service is connected to ingress -svc_connected_to_ingress(svc, ingress) { +svc_connected_to_ingress(svc, ingress) = result { rule := ingress.spec.rules[i] paths := rule.http.paths[j] svc.metadata.name == paths.backend.serviceName - #result := ["service.metadata.name", sprintf("ingress.spec.rules[%d].http.paths[%d].backend.serviceName", [i,j])] + result := [sprintf("ingress.spec.rules[%d].http.paths[%d].backend.serviceName", [i,j])] } diff --git a/rules/exposure-to-internet/test/failed_with_ingress/expected.json b/rules/exposure-to-internet/test/failed_with_ingress/expected.json index e9194e1b1..cb1b49787 100644 --- a/rules/exposure-to-internet/test/failed_with_ingress/expected.json +++ b/rules/exposure-to-internet/test/failed_with_ingress/expected.json @@ -1,35 +1,54 @@ [ { "alertMessage": "workload 'my-app' is exposed through ingress 'my-ingress'", - "fixPaths": [], "failedPaths": [], + "fixPaths": [], "ruleStatus": "", "packagename": "armo_builtins", "alertScore": 7, "alertObject": { "k8sApiObjects": [ - { + { "apiVersion": "apps/v1", "kind": "Deployment", "metadata": { "name": "my-app" } - }, - { - "apiVersion": "v1", - "kind": "Service", - "metadata": { - "name": "my-service" - } - }, - { + } + ] + }, + "relatedObjects": [ + { + "object": { "apiVersion": "networking.k8s.io/v1beta1", "kind": "Ingress", "metadata": { "name": "my-ingress" + }, + "spec": { + "ingressClassName": "nginx", + "rules": [ + { + "host": "myservicea.foo.org", + "http": { + "paths": [ + { + "backend": { + "serviceName": "my-service" + }, + "path": "/" + } + ] + } + } + ] } - } - ] - } + }, + "failedPaths": [ + "ingress.spec.rules[0].http.paths[0].backend.serviceName" + ], + "fixPaths": null + } + ] } -] +] \ No newline at end of file diff --git a/rules/exposure-to-internet/test/failed_with_service_loadbalancer/expected.json b/rules/exposure-to-internet/test/failed_with_service_loadbalancer/expected.json index c282d7264..797e9c436 100644 --- a/rules/exposure-to-internet/test/failed_with_service_loadbalancer/expected.json +++ b/rules/exposure-to-internet/test/failed_with_service_loadbalancer/expected.json @@ -1,28 +1,59 @@ [ { "alertMessage": "workload 'my-app' is exposed through service 'my-service'", - "fixPaths": [], "failedPaths": [], + "fixPaths": [], "ruleStatus": "", "packagename": "armo_builtins", "alertScore": 7, "alertObject": { "k8sApiObjects": [ - { + { "apiVersion": "apps/v1", "kind": "Deployment", "metadata": { "name": "my-app" } - }, - { + } + ] + }, + "relatedObjects": [ + { + "object": { "apiVersion": "v1", "kind": "Service", "metadata": { "name": "my-service" + }, + "spec": { + "clusterIP": "10.96.0.11", + "ports": [ + { + "port": 80, + "protocol": "TCP", + "targetPort": 9376 + } + ], + "selector": { + "app": "argo-server" + }, + "type": "LoadBalancer" + }, + "status": { + "loadBalancer": { + "ingress": [ + { + "ip": "192.0.2.127" + } + ] + } } - } - ] - } + }, + "failedPaths": [ + "spec.type" + ], + "fixPaths": null + } + ] } -] +] \ No newline at end of file diff --git a/rules/exposure-to-internet/test/failed_with_service_loadbalancer/input/service.yaml b/rules/exposure-to-internet/test/failed_with_service_loadbalancer/input/service.yaml index 2286113ac..410565d01 100644 --- a/rules/exposure-to-internet/test/failed_with_service_loadbalancer/input/service.yaml +++ b/rules/exposure-to-internet/test/failed_with_service_loadbalancer/input/service.yaml @@ -4,12 +4,12 @@ metadata: name: my-service spec: selector: - app.kubernetes.io/name: MyApp + app: argo-server ports: - protocol: TCP port: 80 targetPort: 9376 - clusterIP: 10.0.171.239 + clusterIP: 10.96.0.11 type: LoadBalancer status: loadBalancer: diff --git a/rules/exposure-to-internet/test/failed_with_service_nodeport/expected.json b/rules/exposure-to-internet/test/failed_with_service_nodeport/expected.json index 6100000ce..53167dd6c 100644 --- a/rules/exposure-to-internet/test/failed_with_service_nodeport/expected.json +++ b/rules/exposure-to-internet/test/failed_with_service_nodeport/expected.json @@ -1,28 +1,49 @@ [ { - "alertMessage": "workload 'my-app' is exposed through service 'my-service'", - "fixPaths": [], + "alertMessage": "workload 'my-app' is exposed through service 'my-service'", "failedPaths": [], + "fixPaths": [], "ruleStatus": "", "packagename": "armo_builtins", "alertScore": 7, "alertObject": { "k8sApiObjects": [ - { + { "apiVersion": "apps/v1", "kind": "Deployment", "metadata": { "name": "my-app" } - }, - { + } + ] + }, + "relatedObjects": [ + { + "object": { "apiVersion": "v1", "kind": "Service", "metadata": { "name": "my-service" + }, + "spec": { + "ports": [ + { + "nodePort": 30007, + "port": 80, + "targetPort": 80 + } + ], + "selector": { + "app": "argo-server" + }, + "type": "NodePort" } - } - ] - } + }, + "failedPaths": [ + "spec.type" + ], + "fixPaths": null + } + ] } -] +] \ No newline at end of file diff --git a/rules/exposure-to-internet/test/failed_with_service_nodeport/input/service.yaml b/rules/exposure-to-internet/test/failed_with_service_nodeport/input/service.yaml index 70999d7b9..94654bcb9 100644 --- a/rules/exposure-to-internet/test/failed_with_service_nodeport/input/service.yaml +++ b/rules/exposure-to-internet/test/failed_with_service_nodeport/input/service.yaml @@ -3,6 +3,8 @@ kind: Service metadata: name: my-service spec: + selector: + app: argo-server type: NodePort ports: - port: 80 From 484a047e64c4adc7dde6b93abf1f94679dce0940 Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Sun, 16 Jul 2023 12:43:40 +0300 Subject: [PATCH 39/48] add checksVulnerabilities indicator Signed-off-by: YiscahLevySilas1 --- attack-tracks/workload-external-track.json | 1 + 1 file changed, 1 insertion(+) diff --git a/attack-tracks/workload-external-track.json b/attack-tracks/workload-external-track.json index 2018ce2f1..0203face5 100644 --- a/attack-tracks/workload-external-track.json +++ b/attack-tracks/workload-external-track.json @@ -11,6 +11,7 @@ "subSteps": [ { "name": "Vulnerable Image", + "checksVulnerabilities": true, "subSteps": [ { "name": "Data Access" From 03157c41acaeac56b8ce252b1abbd177283790bc Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Sun, 16 Jul 2023 12:43:57 +0300 Subject: [PATCH 40/48] delete old attack tracks Signed-off-by: YiscahLevySilas1 --- attack-tracks/container.json | 54 ------------------------------------ attack-tracks/kubeapi.json | 39 -------------------------- attack-tracks/node.json | 44 ----------------------------- 3 files changed, 137 deletions(-) delete mode 100644 attack-tracks/container.json delete mode 100644 attack-tracks/kubeapi.json delete mode 100644 attack-tracks/node.json diff --git a/attack-tracks/container.json b/attack-tracks/container.json deleted file mode 100644 index 3774587f4..000000000 --- a/attack-tracks/container.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "apiVersion": "regolibrary.kubescape/v1alpha1", - "kind": "AttackTrack", - "metadata": { - "name": "container" - }, - "spec": { - "version": "1.0", - "data": { - "name": "Initial access", - "subSteps": [ - { - "name": "Execution", - "subSteps": [ - { - "name": "Privilege escalation" - }, - { - "name": "Credential access", - "subSteps": [ - { - "name": "Impact - service access" - }, - { - "name": "Impact - K8s API access", - "subSteps": [ - { - "name": "Defense evasion - KubeAPI" - } - ] - } - ] - }, - { - "name": "Discovery" - }, - { - "name": "Lateral movement" - }, - { - "name": "Impact - Data access in container" - }, - { - "name": "Persistence" - } - ] - }, - { - "name": "Impact - service destruction" - } - ] - } - } -} \ No newline at end of file diff --git a/attack-tracks/kubeapi.json b/attack-tracks/kubeapi.json deleted file mode 100644 index 26d79ec47..000000000 --- a/attack-tracks/kubeapi.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "apiVersion": "regolibrary.kubescape/v1alpha1", - "kind": "AttackTrack", - "metadata": { - "name": "kubeapi" - }, - "spec": { - "version": "1.0", - "data": { - "name": "Initial access", - "subSteps": [ - { - "name": "Persistence" - }, - { - "name": "Privilege escalation" - }, - { - "name": "Credential access" - }, - { - "name": "Discovery" - }, - { - "name": "Lateral movement" - }, - { - "name": "Defense evasion" - }, - { - "name": "Impact - data destruction" - }, - { - "name": "Impact - service injection" - } - ] - } - } -} diff --git a/attack-tracks/node.json b/attack-tracks/node.json deleted file mode 100644 index 6b931eab9..000000000 --- a/attack-tracks/node.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "apiVersion": "regolibrary.kubescape/v1alpha1", - "kind": "AttackTrack", - "metadata": { - "name": "node" - }, - "spec": { - "version": "1.0", - "data": { - "name": "Initial access", - "subSteps": [ - { - "name": "Execution", - "subSteps": [ - { - "name": "Persistence" - }, - { - "name": "Credential access" - }, - { - "name": "Defense evasion" - }, - { - "name": "Discovery" - }, - { - "name": "Lateral movement" - }, - { - "name": "Impact - data theft" - }, - { - "name": "Impact - data destruction" - }, - { - "name": "Impact - service injection" - } - ] - } - ] - } - } -} \ No newline at end of file From 5595978e0140d9e8d858f85574c1032f6a0b0455 Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Mon, 17 Jul 2023 08:42:01 +0300 Subject: [PATCH 41/48] changes following review Signed-off-by: YiscahLevySilas1 --- rules/exposure-to-internet/raw.rego | 16 ++++++++-------- .../test/failed_with_ingress/expected.json | 6 ++++-- .../test/failed_with_ingress/input/ingress.yaml | 8 ++++++-- .../test/success_with_ingress/input/ingress.yaml | 8 ++++++-- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/rules/exposure-to-internet/raw.rego b/rules/exposure-to-internet/raw.rego index 37f7077b3..dc098bdcd 100644 --- a/rules/exposure-to-internet/raw.rego +++ b/rules/exposure-to-internet/raw.rego @@ -4,10 +4,10 @@ package armo_builtins deny[msga] { service := input[_] service.kind == "Service" - is_unsafe_service(service) + is_exposed_service(service) wl := input[_] - spec_template_spec_patterns := {"Deployment", "ReplicaSet", "DaemonSet", "StatefulSet", "Pod", "Job"} + spec_template_spec_patterns := {"Deployment", "ReplicaSet", "DaemonSet", "StatefulSet", "Pod", "Job", "CronJob"} spec_template_spec_patterns[wl.kind] wl_connected_to_service(wl, service) failPath := ["spec.type"] @@ -34,10 +34,10 @@ deny[msga] { svc := input[_] svc.kind == "Service" - not is_unsafe_service(svc) + not is_exposed_service(svc) wl := input[_] - spec_template_spec_patterns := {"Deployment", "ReplicaSet", "DaemonSet", "StatefulSet", "Pod", "Job"} + spec_template_spec_patterns := {"Deployment", "ReplicaSet", "DaemonSet", "StatefulSet", "Pod", "Job", "CronJob"} spec_template_spec_patterns[wl.kind] wl_connected_to_service(wl, svc) @@ -61,11 +61,11 @@ deny[msga] { # ==================================================================================== -is_unsafe_service(svc) { +is_exposed_service(svc) { svc.spec.type == "NodePort" } -is_unsafe_service(svc) { +is_exposed_service(svc) { svc.spec.type == "LoadBalancer" } @@ -81,7 +81,7 @@ wl_connected_to_service(wl, svc) { svc_connected_to_ingress(svc, ingress) = result { rule := ingress.spec.rules[i] paths := rule.http.paths[j] - svc.metadata.name == paths.backend.serviceName - result := [sprintf("ingress.spec.rules[%d].http.paths[%d].backend.serviceName", [i,j])] + svc.metadata.name == paths.backend.service.name + result := [sprintf("ingress.spec.rules[%d].http.paths[%d].backend.service.name", [i,j])] } diff --git a/rules/exposure-to-internet/test/failed_with_ingress/expected.json b/rules/exposure-to-internet/test/failed_with_ingress/expected.json index cb1b49787..5bd39611f 100644 --- a/rules/exposure-to-internet/test/failed_with_ingress/expected.json +++ b/rules/exposure-to-internet/test/failed_with_ingress/expected.json @@ -34,7 +34,9 @@ "paths": [ { "backend": { - "serviceName": "my-service" + "service": { + "name": "my-service" + } }, "path": "/" } @@ -45,7 +47,7 @@ } }, "failedPaths": [ - "ingress.spec.rules[0].http.paths[0].backend.serviceName" + "ingress.spec.rules[0].http.paths[0].backend.service.name" ], "fixPaths": null } diff --git a/rules/exposure-to-internet/test/failed_with_ingress/input/ingress.yaml b/rules/exposure-to-internet/test/failed_with_ingress/input/ingress.yaml index a9b2f0e0b..096c24a22 100644 --- a/rules/exposure-to-internet/test/failed_with_ingress/input/ingress.yaml +++ b/rules/exposure-to-internet/test/failed_with_ingress/input/ingress.yaml @@ -1,4 +1,4 @@ -apiVersion: networking.k8s.io/v1beta1 +apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress @@ -9,5 +9,9 @@ spec: http: paths: - path: / + pathType: ImplementationSpecific backend: - serviceName: my-service + service: + name: my-service + port: + number: 80 diff --git a/rules/exposure-to-internet/test/success_with_ingress/input/ingress.yaml b/rules/exposure-to-internet/test/success_with_ingress/input/ingress.yaml index bab67d137..1d707c51f 100644 --- a/rules/exposure-to-internet/test/success_with_ingress/input/ingress.yaml +++ b/rules/exposure-to-internet/test/success_with_ingress/input/ingress.yaml @@ -1,4 +1,4 @@ -apiVersion: networking.k8s.io/v1beta1 +apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress @@ -9,5 +9,9 @@ spec: http: paths: - path: / + pathType: ImplementationSpecific backend: - serviceName: my-service-b + service: + name: my-service-b + port: + number: 80 From cf4c67fc3cd8ebea150aa0d5a6f62c6cfe601a5e Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Mon, 17 Jul 2023 13:30:29 +0300 Subject: [PATCH 42/48] add comment Signed-off-by: YiscahLevySilas1 --- rules/exposure-to-internet/raw.rego | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rules/exposure-to-internet/raw.rego b/rules/exposure-to-internet/raw.rego index dc098bdcd..4a6345c47 100644 --- a/rules/exposure-to-internet/raw.rego +++ b/rules/exposure-to-internet/raw.rego @@ -34,6 +34,8 @@ deny[msga] { svc := input[_] svc.kind == "Service" + # avoid duplicate alerts + # if service is already exposed through NodePort or LoadBalancer workload will fail on that not is_exposed_service(svc) wl := input[_] From 5bb04786eba9147a4e153bdcbc41d195eea65a65 Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Mon, 17 Jul 2023 21:24:12 +0300 Subject: [PATCH 43/48] refactor rule Signed-off-by: YiscahLevySilas1 --- .../raw.rego | 50 ++++++------------- .../input/network_policy2.yaml | 13 +++++ .../expected.json | 1 + .../input/network_policy.yaml | 11 ++++ .../input/pod.yaml | 11 ++++ 5 files changed, 51 insertions(+), 35 deletions(-) create mode 100644 rules/ensure_network_policy_configured_in_labels/test/failed_pod_no_matched_label/input/network_policy2.yaml create mode 100644 rules/ensure_network_policy_configured_in_labels/test/success_pod_no_pod_selector_ns/expected.json create mode 100644 rules/ensure_network_policy_configured_in_labels/test/success_pod_no_pod_selector_ns/input/network_policy.yaml create mode 100644 rules/ensure_network_policy_configured_in_labels/test/success_pod_no_pod_selector_ns/input/pod.yaml diff --git a/rules/ensure_network_policy_configured_in_labels/raw.rego b/rules/ensure_network_policy_configured_in_labels/raw.rego index c96c25667..10fc593d0 100644 --- a/rules/ensure_network_policy_configured_in_labels/raw.rego +++ b/rules/ensure_network_policy_configured_in_labels/raw.rego @@ -2,60 +2,39 @@ package armo_builtins deny[msga] { + workload := input[_] + workload_kinds := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job", "Pod", "CronJob"} + workload_kinds[workload.kind] - resources := get_resources(input[_]) - resource := resources[_] - - # getting all networkpolicies - networkpolicies := [networkpolicy | networkpolicy= input[_]; networkpolicy.kind == "NetworkPolicy"] - - # getting all networkpolicies that are connected to workload with label - network_policies_connected_to_workload := [networkpolicy | networkpolicy= networkpolicies[_]; connected_to_network_policy(resource, networkpolicy)] - - # we expect the number of resources to be equal to the number of networkpolicies connected to the workload. If not, deny. - not count(resources) == count(network_policies_connected_to_workload) + networkpolicies := [networkpolicy | networkpolicy = input[_]; networkpolicy.kind == "NetworkPolicy"] + not connected_to_any_network_policy(workload, networkpolicies) msga := { - "alertMessage": sprintf("%v: no networkpolicy configured in labels", [resource.metadata.name]), + "alertMessage": sprintf("%v: no networkpolicy configured in labels", [workload.metadata.name]), "packagename": "armo_builtins", "failedPaths": [], "fixPaths":[], "alertObject": { - "k8sApiObjects": [resource] + "k8sApiObjects": [workload] } } } -# get_resources returns all resources of kind Deployment, ReplicaSet, DaemonSet, StatefulSet, Job, Pod, CronJob -get_resources(resources) := result { - resource_kinds := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} - resource_kinds[resources.kind] - result = [resources] -} - -# get_resources returns all resources of kind Pod -get_resources(resources) := result { - resources.kind == "Pod" - result = [resources] -} - -# get_resources returns all resources of kind CronJob -get_resources(resources) := result { - resources.kind == "CronJob" - result = [resources] +connected_to_any_network_policy(workload, networkpolicies){ + connected_to_network_policy(workload, networkpolicies[_]) } -# connected_to_network_policy returns true if the resource is connected to the networkpolicy +# connected_to_network_policy returns true if the workload is connected to the networkpolicy connected_to_network_policy(wl, networkpolicy){ - resource_kinds := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} - resource_kinds[wl.kind] + workload_kinds := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} + workload_kinds[wl.kind] is_same_namespace(networkpolicy.metadata, wl.metadata) count(networkpolicy.spec.podSelector) > 0 count({x | networkpolicy.spec.podSelector.matchLabels[x] == wl.spec.template.metadata.labels[x]}) == count(networkpolicy.spec.podSelector.matchLabels) } -# connected_to_network_policy returns true if the resource is connected to the networkpolicy +# connected_to_network_policy returns true if the workload is connected to the networkpolicy connected_to_network_policy(wl, networkpolicy){ wl.kind == "Pod" is_same_namespace(networkpolicy.metadata, wl.metadata) @@ -63,7 +42,7 @@ connected_to_network_policy(wl, networkpolicy){ count({x | networkpolicy.spec.podSelector.matchLabels[x] == wl.metadata.labels[x]}) == count(networkpolicy.spec.podSelector.matchLabels) } -# connected_to_network_policy returns true if the resource is connected to the networkpolicy +# connected_to_network_policy returns true if the workload is connected to the networkpolicy connected_to_network_policy(wl, networkpolicy){ wl.kind == "CronJob" is_same_namespace(networkpolicy.metadata, wl.metadata) @@ -74,6 +53,7 @@ connected_to_network_policy(wl, networkpolicy){ # connected_to_network_policy returns true if the NetworkPolicy has no podSelector. # if the NetworkPolicy has no podSelector, it is applied to all workloads in the namespace of the NetworkPolicy connected_to_network_policy(wl, networkpolicy){ + is_same_namespace(networkpolicy.metadata, wl.metadata) count(networkpolicy.spec.podSelector) == 0 } diff --git a/rules/ensure_network_policy_configured_in_labels/test/failed_pod_no_matched_label/input/network_policy2.yaml b/rules/ensure_network_policy_configured_in_labels/test/failed_pod_no_matched_label/input/network_policy2.yaml new file mode 100644 index 000000000..5a62c5626 --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/failed_pod_no_matched_label/input/network_policy2.yaml @@ -0,0 +1,13 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: my-pod-network-policy2 + namespace: my-namespace +spec: + podSelector: + matchLabels: + app: my-pod + ingress: + - ports: + - protocol: TCP + port: 8080 \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/success_pod_no_pod_selector_ns/expected.json b/rules/ensure_network_policy_configured_in_labels/test/success_pod_no_pod_selector_ns/expected.json new file mode 100644 index 000000000..0637a088a --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/success_pod_no_pod_selector_ns/expected.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/success_pod_no_pod_selector_ns/input/network_policy.yaml b/rules/ensure_network_policy_configured_in_labels/test/success_pod_no_pod_selector_ns/input/network_policy.yaml new file mode 100644 index 000000000..f27c9fe47 --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/success_pod_no_pod_selector_ns/input/network_policy.yaml @@ -0,0 +1,11 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: my-pod-network-policy + namespace: my-namespace +spec: + podSelector: {} + ingress: + - ports: + - protocol: TCP + port: 8080 \ No newline at end of file diff --git a/rules/ensure_network_policy_configured_in_labels/test/success_pod_no_pod_selector_ns/input/pod.yaml b/rules/ensure_network_policy_configured_in_labels/test/success_pod_no_pod_selector_ns/input/pod.yaml new file mode 100644 index 000000000..fc8293967 --- /dev/null +++ b/rules/ensure_network_policy_configured_in_labels/test/success_pod_no_pod_selector_ns/input/pod.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Pod +metadata: + name: my-pod + namespace: my-namespace + labels: + app: my-pod +spec: + containers: + - name: my-app + image: my-app:1.0.0 \ No newline at end of file From ff30dc8453808d3bd8c1084bfa7691eed266e639 Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Mon, 17 Jul 2023 21:40:31 +0300 Subject: [PATCH 44/48] check if system groups that include sa are bound Signed-off-by: YiscahLevySilas1 --- rules/serviceaccount-token-mount/raw.rego | 49 ++++++++++++----------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/rules/serviceaccount-token-mount/raw.rego b/rules/serviceaccount-token-mount/raw.rego index bf905d954..2d512fca8 100644 --- a/rules/serviceaccount-token-mount/raw.rego +++ b/rules/serviceaccount-token-mount/raw.rego @@ -1,9 +1,7 @@ package armo_builtins -# -- ---- For workloads -- ---- -# Fails if pod mount tokens by default (either by its config or by its SA config) - # POD +# POD deny [msga]{ pod := input[_] pod.kind == "Pod" @@ -80,31 +78,19 @@ is_sa_auto_mounted(spec, beggining_of_path, wl_namespace) = [failed_path, fix_pa not spec.automountServiceAccountToken == false not spec.automountServiceAccountToken == true - # check if SA automount by default sa := input[_] is_same_sa(spec, sa.metadata.name) is_same_namespace(sa.metadata.namespace , wl_namespace) has_service_account_binding(sa) - # path is pod spec fix_path = { "path": sprintf("%vautomountServiceAccountToken", [beggining_of_path]), "value": "false"} failed_path = "" } -get_failed_path(paths) = [paths[0]] { - paths[0] != "" -} else = [] - - -get_fixed_path(paths) = [paths[1]] { - paths[1] != "" -} else = [] - is_sa_auto_mounted(spec, beggining_of_path, wl_namespace) = [failed_path, fix_path] { # automountServiceAccountToken set to true in pod spec spec.automountServiceAccountToken == true - # SA automount by default service_accounts := [service_account | service_account = input[_]; service_account.kind == "ServiceAccount"] count(service_accounts) > 0 sa := service_accounts[_] @@ -116,6 +102,16 @@ is_sa_auto_mounted(spec, beggining_of_path, wl_namespace) = [failed_path, fix_p fix_path = "" } +get_failed_path(paths) = [paths[0]] { + paths[0] != "" +} else = [] + + +get_fixed_path(paths) = [paths[1]] { + paths[1] != "" +} else = [] + + is_same_sa(spec, serviceAccountName) { spec.serviceAccountName == serviceAccountName } @@ -144,20 +140,27 @@ is_same_namespace(metadata1, metadata2) { metadata2.namespace == "default" } -# checks if RoleBinding has a bind with the given ServiceAccount +# checks if RoleBinding/ClusterRoleBinding has a bind with the given ServiceAccount has_service_account_binding(service_account) { - role_bindings := [role_binding | role_binding = input[_]; role_binding.kind == "RoleBinding"] + role_bindings := [role_binding | role_binding = input[_]; endswith(role_binding.kind, "Binding")] role_binding := role_bindings[_] role_binding.subjects[_].name == service_account.metadata.name role_binding.subjects[_].namespace == service_account.metadata.namespace role_binding.subjects[_].kind == "ServiceAccount" } -# checks if ClusterRoleBinding has a bind with the given ServiceAccount +# checks if RoleBinding/ClusterRoleBinding has a bind with the system:authenticated group +# which gives access to all authenticated users, including service accounts +has_service_account_binding(service_account) { + role_bindings := [role_binding | role_binding = input[_]; endswith(role_binding.kind, "Binding")] + role_binding := role_bindings[_] + role_binding.subjects[_].name == "system:authenticated" +} + +# checks if RoleBinding/ClusterRoleBinding has a bind with the "system:serviceaccounts" group +# which gives access to all service accounts has_service_account_binding(service_account) { - cluster_role_bindings := [cluster_role_binding | cluster_role_binding = input[_]; cluster_role_binding.kind == "ClusterRoleBinding"] - cluster_role_binding := cluster_role_bindings[_] - cluster_role_binding.subjects[_].name == service_account.metadata.name - cluster_role_binding.subjects[_].namespace == service_account.metadata.namespace - cluster_role_binding.subjects[_].kind == "ServiceAccount" + role_bindings := [role_binding | role_binding = input[_]; endswith(role_binding.kind, "Binding")] + role_binding := role_bindings[_] + role_binding.subjects[_].name == "system:serviceaccounts" } From 0bccb2ff1049660b1a7fe7ee269fa40763b1f526 Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Mon, 17 Jul 2023 22:17:22 +0300 Subject: [PATCH 45/48] refactor rule and add related object Signed-off-by: YiscahLevySilas1 --- rules/serviceaccount-token-mount/raw.rego | 92 +++++++---------------- 1 file changed, 28 insertions(+), 64 deletions(-) diff --git a/rules/serviceaccount-token-mount/raw.rego b/rules/serviceaccount-token-mount/raw.rego index 2d512fca8..e252dd159 100644 --- a/rules/serviceaccount-token-mount/raw.rego +++ b/rules/serviceaccount-token-mount/raw.rego @@ -1,88 +1,59 @@ package armo_builtins - -# POD -deny [msga]{ - pod := input[_] - pod.kind == "Pod" - - beggining_of_path := "spec." - wl_namespace := pod.metadata.namespace - result := is_sa_auto_mounted(pod.spec, beggining_of_path, wl_namespace) - failed_path := get_failed_path(result) - fixed_path := get_fixed_path(result) - - msga := { - "alertMessage": sprintf("Pod: %v in the following namespace: %v mounts service account tokens by default", [pod.metadata.name, pod.metadata.namespace]), - "alertScore": 9, - "packagename": "armo_builtins", - "fixPaths": fixed_path, - "failedPaths": failed_path, - "alertObject": { - "k8sApiObjects": [pod] - } - } -} - -# WORKLOADS deny[msga] { wl := input[_] - spec_template_spec_patterns := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} - spec_template_spec_patterns[wl.kind] - beggining_of_path := "spec.template.spec." + beggining_of_path := get_beginning_of_path(wl) wl_namespace := wl.metadata.namespace - result := is_sa_auto_mounted(wl.spec.template.spec, beggining_of_path, wl_namespace) + result := is_sa_auto_mounted(wl.spec.jobTemplate.spec.template.spec, beggining_of_path, wl_namespace) + + sa := input[_] + is_same_sa(spec, sa.metadata.name) + is_same_namespace(sa.metadata.namespace , wl_namespace) + has_service_account_binding(sa) + failed_path := get_failed_path(result) fixed_path := get_fixed_path(result) msga := { - "alertMessage": sprintf("%v: %v in the following namespace: %v mounts service account tokens by default", [wl.kind, wl.metadata.name, wl.metadata.namespace]), + "alertMessage": sprintf("%v: %v in the following namespace: %v mounts service account tokens by default", [wl.kind, wl.metadata.name, wl.metadata.namespace]), "packagename": "armo_builtins", "alertScore": 7, "fixPaths": fixed_path, "failedPaths": failed_path, "alertObject": { "k8sApiObjects": [wl] - } + }, + "relatedObjects": [{ + "object": sa + }] } } -# CRONJOB -deny[msga] { - wl := input[_] - wl.kind == "CronJob" - container = wl.spec.jobTemplate.spec.template.spec.containers[i] - beggining_of_path := "spec.jobTemplate.spec.template.spec." - - wl_namespace := wl.metadata.namespace - result := is_sa_auto_mounted(wl.spec.jobTemplate.spec.template.spec, beggining_of_path, wl_namespace) - failed_path := get_failed_path(result) - fixed_path := get_fixed_path(result) - msga := { - "alertMessage": sprintf("%v: %v in the following namespace: %v mounts service account tokens by default", [wl.kind, wl.metadata.name, wl.metadata.namespace]), - "packagename": "armo_builtins", - "alertScore": 7, - "fixPaths": fixed_path, - "failedPaths": failed_path, - "alertObject": { - "k8sApiObjects": [wl] - } - } +get_beginning_of_path(workload) = beggining_of_path { + spec_template_spec_patterns := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} + spec_template_spec_patterns[workload.kind] + beggining_of_path := "spec.template.spec." +} + +get_beginning_of_path(workload) = beggining_of_path { + workload.kind == "Pod" + beggining_of_path := "spec." +} + +get_beginning_of_path(workload) = beggining_of_path { + workload.kind == "CronJob" + beggining_of_path := "spec.jobTemplate.spec.template.spec." } + # -- ---- For workloads -- ---- is_sa_auto_mounted(spec, beggining_of_path, wl_namespace) = [failed_path, fix_path] { # automountServiceAccountToken not in pod spec not spec.automountServiceAccountToken == false not spec.automountServiceAccountToken == true - sa := input[_] - is_same_sa(spec, sa.metadata.name) - is_same_namespace(sa.metadata.namespace , wl_namespace) - has_service_account_binding(sa) - fix_path = { "path": sprintf("%vautomountServiceAccountToken", [beggining_of_path]), "value": "false"} failed_path = "" } @@ -90,13 +61,6 @@ is_sa_auto_mounted(spec, beggining_of_path, wl_namespace) = [failed_path, fix_pa is_sa_auto_mounted(spec, beggining_of_path, wl_namespace) = [failed_path, fix_path] { # automountServiceAccountToken set to true in pod spec spec.automountServiceAccountToken == true - - service_accounts := [service_account | service_account = input[_]; service_account.kind == "ServiceAccount"] - count(service_accounts) > 0 - sa := service_accounts[_] - is_same_sa(spec, sa.metadata.name) - is_same_namespace(sa.metadata.namespace , wl_namespace) - has_service_account_binding(sa) failed_path = sprintf("%vautomountServiceAccountToken", [beggining_of_path]) fix_path = "" From 266d8ec0010e86664225982d692d1b7a0b4af7d9 Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Mon, 17 Jul 2023 22:17:45 +0300 Subject: [PATCH 46/48] refactor rule and add related object Signed-off-by: YiscahLevySilas1 --- rules/serviceaccount-token-mount/raw.rego | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/rules/serviceaccount-token-mount/raw.rego b/rules/serviceaccount-token-mount/raw.rego index e252dd159..2474ccb95 100644 --- a/rules/serviceaccount-token-mount/raw.rego +++ b/rules/serviceaccount-token-mount/raw.rego @@ -3,9 +3,10 @@ package armo_builtins deny[msga] { wl := input[_] beggining_of_path := get_beginning_of_path(wl) + spec := object.get(wl, beggining_of_path, []) wl_namespace := wl.metadata.namespace - result := is_sa_auto_mounted(wl.spec.jobTemplate.spec.template.spec, beggining_of_path, wl_namespace) + result := is_sa_auto_mounted(spec, beggining_of_path, wl_namespace) sa := input[_] is_same_sa(spec, sa.metadata.name) @@ -34,17 +35,17 @@ deny[msga] { get_beginning_of_path(workload) = beggining_of_path { spec_template_spec_patterns := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} spec_template_spec_patterns[workload.kind] - beggining_of_path := "spec.template.spec." + beggining_of_path := ["spec", "template", "spec"] } get_beginning_of_path(workload) = beggining_of_path { workload.kind == "Pod" - beggining_of_path := "spec." + beggining_of_path := ["spec"] } get_beginning_of_path(workload) = beggining_of_path { workload.kind == "CronJob" - beggining_of_path := "spec.jobTemplate.spec.template.spec." + beggining_of_path := ["spec", "jobTemplate", "spec", "template", "spec"] } @@ -54,7 +55,7 @@ is_sa_auto_mounted(spec, beggining_of_path, wl_namespace) = [failed_path, fix_pa not spec.automountServiceAccountToken == false not spec.automountServiceAccountToken == true - fix_path = { "path": sprintf("%vautomountServiceAccountToken", [beggining_of_path]), "value": "false"} + fix_path = { "path": sprintf("%v.automountServiceAccountToken", [concat(".", containers_path)]), "value": "false"} failed_path = "" } @@ -62,7 +63,7 @@ is_sa_auto_mounted(spec, beggining_of_path, wl_namespace) = [failed_path, fix_p # automountServiceAccountToken set to true in pod spec spec.automountServiceAccountToken == true - failed_path = sprintf("%vautomountServiceAccountToken", [beggining_of_path]) + failed_path = sprintf("%v.automountServiceAccountToken", [concat(".", containers_path)]) fix_path = "" } From 3782b3d4ffb15c0b6486892e6a21970aaf00c10a Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Mon, 17 Jul 2023 22:18:04 +0300 Subject: [PATCH 47/48] add related object Signed-off-by: YiscahLevySilas1 --- rules/workload-mounted-configmap/raw.rego | 5 +- rules/workload-mounted-pvc/raw.rego | 5 +- rules/workload-mounted-secrets/raw.rego | 12 ++--- .../test/failed/expected.json | 48 +------------------ 4 files changed, 14 insertions(+), 56 deletions(-) diff --git a/rules/workload-mounted-configmap/raw.rego b/rules/workload-mounted-configmap/raw.rego index eb8f732e1..ad01ec974 100644 --- a/rules/workload-mounted-configmap/raw.rego +++ b/rules/workload-mounted-configmap/raw.rego @@ -30,7 +30,10 @@ deny[msga] { "fixPaths":[], "alertObject": { "k8sApiObjects": [resource] -} + }, + "relatedObjects": [{ + "object": configMap + }] } } diff --git a/rules/workload-mounted-pvc/raw.rego b/rules/workload-mounted-pvc/raw.rego index 904c5d25d..1e9a535c3 100644 --- a/rules/workload-mounted-pvc/raw.rego +++ b/rules/workload-mounted-pvc/raw.rego @@ -29,7 +29,10 @@ deny[msga] { "fixPaths":[], "alertObject": { "k8sApiObjects": [resource] -} + }, + "relatedObjects": [{ + "object": PVC + }] } } diff --git a/rules/workload-mounted-secrets/raw.rego b/rules/workload-mounted-secrets/raw.rego index feba85329..fa6076cd7 100644 --- a/rules/workload-mounted-secrets/raw.rego +++ b/rules/workload-mounted-secrets/raw.rego @@ -12,10 +12,6 @@ deny[msga] { secret.metadata.name == volume.secret.secretName is_same_namespace(secret.metadata, resource.metadata) - # add related ressource - resource_vector := json.patch(resource, [{"op": "add", "path": "relatedObjects", "value": [secret]}]) - - containers_path := get_containers_path(resource) containers := object.get(resource, containers_path, []) container := containers[j] @@ -32,9 +28,11 @@ deny[msga] { "failedPaths": [failedPaths], "fixPaths":[], "alertObject": { - "k8sApiObjects": [resource], - "externalObjects": resource_vector - } + "k8sApiObjects": [resource] + }, + "relatedObjects": [{ + "object": secret + }] } } diff --git a/rules/workload-mounted-secrets/test/failed/expected.json b/rules/workload-mounted-secrets/test/failed/expected.json index 02202e6e0..177f27a7e 100644 --- a/rules/workload-mounted-secrets/test/failed/expected.json +++ b/rules/workload-mounted-secrets/test/failed/expected.json @@ -17,53 +17,7 @@ "name": "mypod" } } - ], - "externalObjects": { - "apiVersion": "v1", - "kind": "Pod", - "metadata": { - "name": "mypod", - "namespace": "default" - }, - "relatedObjects": [ - { - "apiVersion": "v1", - "data": { - "password": "MWYyZDFlMmU2N2Rm", - "username": "YWRtaW4=" - }, - "kind": "Secret", - "metadata": { - "name": "mysecret" - }, - "type": "Opaque" - } - ], - "spec": { - "containers": [ - { - "image": "redis", - "name": "mypod", - "volumeMounts": [ - { - "mountPath": "/etc/foo", - "name": "foo", - "readOnly": true - } - ] - } - ], - "volumes": [ - { - "name": "foo", - "secret": { - "optional": true, - "secretName": "mysecret" - } - } - ] - } - } + ] } } ] \ No newline at end of file From 1b28a4e6555e03218f392546b16411d4e32f17a7 Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Mon, 17 Jul 2023 22:45:49 +0300 Subject: [PATCH 48/48] fix rule and rulename Signed-off-by: YiscahLevySilas1 --- controls/C-0261-satokenmounted.json | 2 +- rules/serviceaccount-token-mount/raw.rego | 6 +++--- rules/serviceaccount-token-mount/rule.metadata.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/controls/C-0261-satokenmounted.json b/controls/C-0261-satokenmounted.json index f57ad3ef7..f2216f5e6 100644 --- a/controls/C-0261-satokenmounted.json +++ b/controls/C-0261-satokenmounted.json @@ -16,7 +16,7 @@ }, "description": "Potential attacker may gain access to a workload and steal its ServiceAccount token. Therefore, it is recommended to disable automatic mapping of the ServiceAccount tokens in ServiceAccount configuration. Enable it only for workloads that need to use them and ensure that this ServiceAccount is not bound to an unnecessary ClusterRoleBinding or RoleBinding.", "remediation": "Disable automatic mounting of service account tokens to pods at the workload level, by specifying automountServiceAccountToken: false. Enable it only for workloads that need to use them and ensure that this ServiceAccount doesn't have unnecessary permissions", - "rulesNames": ["automount-service-account"], + "rulesNames": ["serviceaccount-token-mount"], "test": "test if ServiceAccount token is mounted on workload and it has at least one binding.", "controlID": "C-0261", "baseScore": 7.0 diff --git a/rules/serviceaccount-token-mount/raw.rego b/rules/serviceaccount-token-mount/raw.rego index 2474ccb95..f11e8ea29 100644 --- a/rules/serviceaccount-token-mount/raw.rego +++ b/rules/serviceaccount-token-mount/raw.rego @@ -19,7 +19,7 @@ deny[msga] { msga := { "alertMessage": sprintf("%v: %v in the following namespace: %v mounts service account tokens by default", [wl.kind, wl.metadata.name, wl.metadata.namespace]), "packagename": "armo_builtins", - "alertScore": 7, + "alertScore": 9, "fixPaths": fixed_path, "failedPaths": failed_path, "alertObject": { @@ -55,7 +55,7 @@ is_sa_auto_mounted(spec, beggining_of_path, wl_namespace) = [failed_path, fix_pa not spec.automountServiceAccountToken == false not spec.automountServiceAccountToken == true - fix_path = { "path": sprintf("%v.automountServiceAccountToken", [concat(".", containers_path)]), "value": "false"} + fix_path = { "path": sprintf("%v.automountServiceAccountToken", [concat(".", beggining_of_path)]), "value": "false"} failed_path = "" } @@ -63,7 +63,7 @@ is_sa_auto_mounted(spec, beggining_of_path, wl_namespace) = [failed_path, fix_p # automountServiceAccountToken set to true in pod spec spec.automountServiceAccountToken == true - failed_path = sprintf("%v.automountServiceAccountToken", [concat(".", containers_path)]) + failed_path = sprintf("%v.automountServiceAccountToken", [concat(".", beggining_of_path)]) fix_path = "" } diff --git a/rules/serviceaccount-token-mount/rule.metadata.json b/rules/serviceaccount-token-mount/rule.metadata.json index b62fd3678..c10e5c9f2 100644 --- a/rules/serviceaccount-token-mount/rule.metadata.json +++ b/rules/serviceaccount-token-mount/rule.metadata.json @@ -1,5 +1,5 @@ { - "name": "automount-service-account", + "name": "serviceaccount-token-mount", "attributes": { "armoBuiltin": true },