diff --git a/go.mod b/go.mod
index 0cf02ba2..3fbf8df6 100644
--- a/go.mod
+++ b/go.mod
@@ -13,6 +13,8 @@ replace (
k8s.io/cli-runtime => k8s.io/cli-runtime v0.26.4
k8s.io/client-go => k8s.io/client-go v0.26.4
k8s.io/component-base => k8s.io/component-base v0.26.4
+ sigs.k8s.io/kustomize/api => sigs.k8s.io/kustomize/api v0.12.1
+ sigs.k8s.io/kustomize/kyaml => sigs.k8s.io/kustomize/kyaml v0.13.9
)
require (
@@ -41,7 +43,7 @@ require (
)
require (
- github.com/accuknox/auto-policy-discovery/src v0.0.0-20230427074403-5d03ee9f3358
+ github.com/accuknox/auto-policy-discovery/src v0.0.0-20230605060121-abe7d0b9770d
github.com/cavaliergopher/grab/v3 v3.0.1
github.com/charmbracelet/bubbles v0.15.0
github.com/charmbracelet/bubbletea v0.23.2
@@ -62,7 +64,7 @@ require (
k8s.io/api v0.27.1
k8s.io/apiextensions-apiserver v0.27.1
k8s.io/apimachinery v0.27.1
- k8s.io/cli-runtime v0.26.4
+ k8s.io/cli-runtime v0.27.1
k8s.io/client-go v0.27.1
k8s.io/utils v0.0.0-20230505201702-9f6742963106
)
@@ -173,7 +175,6 @@ require (
github.com/gobwas/glob v0.2.3 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
- github.com/golang/glog v1.1.1 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
@@ -185,7 +186,7 @@ require (
github.com/google/go-github/v45 v45.2.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
- github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
+ github.com/google/pprof v0.0.0-20211008130755-947d60d73cc0 // indirect
github.com/google/s2a-go v0.1.2 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/trillian v1.5.1 // indirect
@@ -268,7 +269,7 @@ require (
github.com/shibumi/go-pathspec v1.3.0 // indirect
github.com/shirou/gopsutil/v3 v3.23.3 // indirect
github.com/sigstore/cosign v1.13.1 // indirect
- github.com/sigstore/fulcio v1.0.0 // indirect
+ github.com/sigstore/fulcio v1.1.0 // indirect
github.com/sigstore/k8s-manifest-sigstore v0.4.4 // indirect
github.com/sigstore/rekor v1.0.1 // indirect
github.com/sigstore/sigstore v1.5.2 // indirect
@@ -330,12 +331,12 @@ require (
k8s.io/component-base v0.27.1 // indirect
k8s.io/klog/v2 v2.100.1 // indirect
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect
- k8s.io/kubectl v0.26.4 // indirect
- k8s.io/pod-security-admission v0.26.4 // indirect
+ k8s.io/kubectl v0.27.1 // indirect
+ k8s.io/pod-security-admission v0.27.1 // indirect
sigs.k8s.io/controller-runtime v0.14.6 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
- sigs.k8s.io/kustomize/api v0.12.1 // indirect
- sigs.k8s.io/kustomize/kyaml v0.13.9 // indirect
+ sigs.k8s.io/kustomize/api v0.13.2 // indirect
+ sigs.k8s.io/kustomize/kyaml v0.14.1 // indirect
sigs.k8s.io/release-utils v0.7.3 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
)
diff --git a/go.sum b/go.sum
index 95726e52..3e4b0d47 100644
--- a/go.sum
+++ b/go.sum
@@ -128,8 +128,8 @@ github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrU
github.com/ThalesIgnite/crypto11 v1.2.5 h1:1IiIIEqYmBvUYFeMnHqRft4bwf/O36jryEUpY+9ef8E=
github.com/ThalesIgnite/crypto11 v1.2.5/go.mod h1:ILDKtnCKiQ7zRoNxcp36Y1ZR8LBPmR2E23+wTQe/MlE=
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
-github.com/accuknox/auto-policy-discovery/src v0.0.0-20230427074403-5d03ee9f3358 h1:X8XLPGOoQk0ZBxqkjcpZ8aD4Ez18HW6q3zjj7bjo/7s=
-github.com/accuknox/auto-policy-discovery/src v0.0.0-20230427074403-5d03ee9f3358/go.mod h1:q1d217En1e+b4ZVx8Royu7kUhku5FP6hGU6WJqI2zQY=
+github.com/accuknox/auto-policy-discovery/src v0.0.0-20230605060121-abe7d0b9770d h1:LeEH2EzbgfpdmsehXMsGDTv5bvM8egIf0A54s7xroWE=
+github.com/accuknox/auto-policy-discovery/src v0.0.0-20230605060121-abe7d0b9770d/go.mod h1:GRLEabyrosgCvcFRoAPcKcHyv5XUKLP7gWxMuF1ip4g=
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8=
github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo=
@@ -626,7 +626,6 @@ github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
github.com/golang/glog v1.1.1 h1:jxpi2eWoU84wbX9iIEyAeeoac3FLuifZpY9tcNUD9kw=
-github.com/golang/glog v1.1.1/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ=
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/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -744,8 +743,9 @@ github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/pprof v0.0.0-20211008130755-947d60d73cc0 h1:zHs+jv3LO743/zFGcByu2KmpbliCU2AhjcGgrdTwSG4=
+github.com/google/pprof v0.0.0-20211008130755-947d60d73cc0/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/s2a-go v0.1.2 h1:WVtYAYuYxKeYajAmThMRYWP6K3wXkcqbGHeUgeubUHY=
github.com/google/s2a-go v0.1.2/go.mod h1:OJpEgntRZo8ugHpF9hkoLJbS5dSI20XZeXJ9JVywLlM=
@@ -849,6 +849,7 @@ github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
@@ -1359,8 +1360,8 @@ github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOms
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sigstore/cosign v1.13.1 h1:+5oF8jisEcDw2TuXxCADC1u5//HfdnJhGbpv9Isiwu4=
github.com/sigstore/cosign v1.13.1/go.mod h1:PlfJODkovUOKsLrGI7Su57Ie/Eb/Ks7hRHw3tn5hQS4=
-github.com/sigstore/fulcio v1.0.0 h1:hBZW6qg9GXTtCX8jOg1hmyjYLrmsEKZGeMwAbW3XNEg=
-github.com/sigstore/fulcio v1.0.0/go.mod h1:j4MzLxX/Be0rHYh3JF2dgMorkWGzEMHBqIHwFU8I/Rw=
+github.com/sigstore/fulcio v1.1.0 h1:mzzJ05Ccu8Y2inyioklNvc8MpzlGHxu8YqNeTm0dHfU=
+github.com/sigstore/fulcio v1.1.0/go.mod h1:zv1ZQTXZbUwQdRwajlQksc34pRas+2aZYpIZoQBNev8=
github.com/sigstore/k8s-manifest-sigstore v0.4.4 h1:7ae///+L0nqFBsRwr26anJc5bnJxoDXCGhVHXQB1GSo=
github.com/sigstore/k8s-manifest-sigstore v0.4.4/go.mod h1:PJSnSF8Nh7PqV4xhU3BRweqEFwGvJq6Xi2B5yhYjxb0=
github.com/sigstore/rekor v1.0.1 h1:rcESXSNkAPRWFYZel9rarspdvneET60F2ngNkadi89c=
@@ -2356,10 +2357,10 @@ k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iL
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4=
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg=
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg=
-k8s.io/kubectl v0.26.4 h1:A0Oa0u/po4KxXnXsNCOwLojAe9cQR3TJNJabEIf7U1w=
-k8s.io/kubectl v0.26.4/go.mod h1:cWtp/+I4p+h5En3s2zO1zCry9v3/6h37EQ2tF3jNRnM=
-k8s.io/pod-security-admission v0.26.4 h1:BfjUrTdJ3jvOK4UW+nshcD7q+/AGLb1gSoqQKbUALnk=
-k8s.io/pod-security-admission v0.26.4/go.mod h1:WjQF+oeXfuXz3iqYc/0XaBAoTOwZ5woLXOC1xswWpa0=
+k8s.io/kubectl v0.27.1 h1:9T5c5KdpburYiW8XKQSH0Uly1kMNE90aGSnbYUZNdcA=
+k8s.io/kubectl v0.27.1/go.mod h1:QsAkSmrRsKTPlAFzF8kODGDl4p35BIwQnc9XFhkcsy8=
+k8s.io/pod-security-admission v0.27.1 h1:if4d1zzcpNOZNvljvJ0nTCshFPUmnkIsy7KYJg7FP08=
+k8s.io/pod-security-admission v0.27.1/go.mod h1:dICAHAC4DE0q+yrGuPJ8kuJ5dEsWtqNkclzCDckHj/s=
k8s.io/utils v0.0.0-20210111153108-fddb29f9d009/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-20221107191617-1a15be271d1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
diff --git a/recommend/admissionControllerPolicy.go b/recommend/admissionControllerPolicy.go
index 7e152d80..b1b05c28 100644
--- a/recommend/admissionControllerPolicy.go
+++ b/recommend/admissionControllerPolicy.go
@@ -3,12 +3,14 @@ package recommend
import (
"context"
"errors"
+ "fmt"
"os"
"strconv"
"strings"
"github.com/accuknox/auto-policy-discovery/src/libs"
"github.com/accuknox/auto-policy-discovery/src/protobuf/v1/worker"
+ "github.com/accuknox/auto-policy-discovery/src/types"
"github.com/clarketm/json"
"github.com/fatih/color"
"github.com/kubearmor/kubearmor-client/k8s"
@@ -18,6 +20,7 @@ import (
"golang.org/x/exp/slices"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
+ "sigs.k8s.io/yaml"
)
var connection *grpc.ClientConn
@@ -74,7 +77,7 @@ func recommendAdmissionControllerPolicies(img ImageInfo) error {
resp, err := client.Convert(context.Background(), &worker.WorkerRequest{
Labels: labels,
Namespace: img.Namespace,
- Policytype: "AdmissionControllerPolicy",
+ Policytype: types.PolicyTypeAdmissionController,
})
if err != nil {
color.Red(err.Error())
@@ -82,21 +85,65 @@ func recommendAdmissionControllerPolicies(img ImageInfo) error {
}
if resp.AdmissionControllerPolicy != nil {
for _, policy := range resp.AdmissionControllerPolicy {
- var kyvernoPolicy kyvernov1.Policy
- err := json.Unmarshal(policy.Data, &kyvernoPolicy)
+ var kyvernoPolicyInterface kyvernov1.PolicyInterface
+ kyvernoPolicyInterface, err = getKyvernoPolicy(policy.Data)
if err != nil {
return err
}
- if namespaceMatches(kyvernoPolicy.Namespace) && matchAdmissionControllerPolicyTags(&kyvernoPolicy) {
- img.writeAdmissionControllerPolicy(kyvernoPolicy)
+ if namespaceMatches(kyvernoPolicyInterface.GetNamespace()) && matchAdmissionControllerPolicyTags(kyvernoPolicyInterface.GetAnnotations()) {
+ img.writeAdmissionControllerPolicy(kyvernoPolicyInterface)
}
}
}
return nil
}
-func matchAdmissionControllerPolicyTags(policy *kyvernov1.Policy) bool {
- policyTags := strings.Split(policy.Annotations["recommended-policies.kubearmor.io/tags"], ",")
+func recommendGenericAdmissionControllerPolicies() error {
+ client := worker.NewWorkerClient(connection)
+ resp, err := client.Convert(context.Background(), &worker.WorkerRequest{
+ Policytype: types.PolicyTypeAdmissionControllerGeneric,
+ })
+ if err != nil {
+ color.Red(err.Error())
+ return err
+ }
+ if resp.AdmissionControllerPolicy != nil {
+ reportStarted := false
+ for _, policy := range resp.AdmissionControllerPolicy {
+ var kyvernoPolicyInterface kyvernov1.PolicyInterface
+ kyvernoPolicyInterface, err = getKyvernoPolicy(policy.Data)
+ if err != nil {
+ if reportStarted {
+ err := ReportSectEnd()
+ if err != nil {
+ return err
+ }
+ }
+ return err
+ }
+ if matchAdmissionControllerPolicyTags(kyvernoPolicyInterface.GetAnnotations()) {
+ if !reportStarted {
+ err := ReportStartGenericAdmissionControllerPolicies()
+ if err != nil {
+ return err
+ }
+ reportStarted = true
+ }
+ writeGenericAdmissionControllerPolicy(kyvernoPolicyInterface)
+ }
+ }
+ if reportStarted {
+ err := ReportSectEnd()
+ if err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+func matchAdmissionControllerPolicyTags(policyAnnotations map[string]string) bool {
+ policyTags := strings.Split(policyAnnotations[types.RecommendedPolicyTagsAnnotation], ",")
if len(options.Tags) <= 0 {
return true
}
@@ -111,3 +158,55 @@ func matchAdmissionControllerPolicyTags(policy *kyvernov1.Policy) bool {
func namespaceMatches(policyNamespace string) bool {
return options.Namespace == "" || options.Namespace == policyNamespace
}
+
+func getKyvernoPolicy(policyYaml []byte) (kyvernov1.PolicyInterface, error) {
+ var policy map[string]interface{}
+ err := yaml.Unmarshal(policyYaml, &policy)
+ if err != nil {
+ return nil, err
+ }
+ policyKind := policy["kind"].(string)
+
+ var kyvernoPolicyInterface kyvernov1.PolicyInterface
+ switch policyKind {
+ case "Policy":
+ var kyvernoPolicy kyvernov1.Policy
+ err = yaml.Unmarshal(policyYaml, &kyvernoPolicy)
+ if err != nil {
+ return nil, err
+ }
+ kyvernoPolicyInterface = &kyvernoPolicy
+ case "ClusterPolicy":
+ var kyvernoClusterPolicy kyvernov1.ClusterPolicy
+ err = yaml.Unmarshal(policyYaml, &kyvernoClusterPolicy)
+ if err != nil {
+ return nil, err
+ }
+ kyvernoPolicyInterface = &kyvernoClusterPolicy
+ default:
+ return nil, fmt.Errorf("unexpected policy kind: %s", policyKind)
+ }
+ return kyvernoPolicyInterface, nil
+}
+
+func convertKyvernoPolicyInterfaceToJSON(policyInterface kyvernov1.PolicyInterface) ([]byte, error) {
+ var jsonBytes []byte
+ var err error
+ switch policyInterface.(type) {
+ case *kyvernov1.ClusterPolicy:
+ kyvernoClusterPolicy := policyInterface.(*kyvernov1.ClusterPolicy)
+ jsonBytes, err = json.Marshal(*kyvernoClusterPolicy)
+ if err != nil {
+ log.WithError(err).Error("json marshal failed")
+ return nil, err
+ }
+ case *kyvernov1.Policy:
+ kyvernoPolicy := policyInterface.(*kyvernov1.Policy)
+ jsonBytes, err = json.Marshal(*kyvernoPolicy)
+ if err != nil {
+ log.WithError(err).Error("json marshal failed")
+ return nil, err
+ }
+ }
+ return jsonBytes, nil
+}
diff --git a/recommend/html/css/main.css b/recommend/html/css/main.css
index b3c45818..b9fd2483 100644
--- a/recommend/html/css/main.css
+++ b/recommend/html/css/main.css
@@ -99,6 +99,11 @@ body {
position: fixed;
overflow: hidden;
}
+.v38_7030 {
+ color: #0b4296;
+ font-family: 'Red Hat Display';
+ font-weight: Bold;
+}
#wrapper {
text-align: center;
overflow: hidden;
diff --git a/recommend/html/section.html b/recommend/html/section.html
index 551474d3..ea347d79 100644
--- a/recommend/html/section.html
+++ b/recommend/html/section.html
@@ -2,14 +2,18 @@
-
- {{range .ImgInfo}}
-
- {{.Key}} |
- : {{.Val}} |
-
- {{end}}
-
+ {{if .GenericAdmissionControllerPolicy}}
+
Generic Kyverno Policies
+ {{else}}
+
+ {{range .ImgInfo}}
+
+ {{.Key}} |
+ : {{.Val}} |
+
+ {{end}}
+
+ {{end}}
diff --git a/recommend/imageHandler.go b/recommend/imageHandler.go
index 2a91fcda..4d102244 100644
--- a/recommend/imageHandler.go
+++ b/recommend/imageHandler.go
@@ -542,7 +542,11 @@ func imageHandler(namespace, deployment string, labels LabelMap, imageName strin
if !containsKyvernoPolicy && !containsKubeArmorPolicy {
return fmt.Errorf("policy type not supported: %v", options.Policy)
}
- _ = ReportSectEnd(&img)
+ err := ReportSectEnd()
+ if err != nil {
+ log.WithError(err).Error("report section end failed")
+ return err
+ }
return nil
}
diff --git a/recommend/policy.go b/recommend/policy.go
index 3755b418..84f0e09b 100644
--- a/recommend/policy.go
+++ b/recommend/policy.go
@@ -136,30 +136,96 @@ func (img *ImageInfo) writePolicyFile(ms MatchSpec) {
}
-func (img *ImageInfo) writeAdmissionControllerPolicy(policy kyvernov1.Policy) {
- policyName := strings.ReplaceAll(policy.Name, img.Name+"-", "")
+func (img *ImageInfo) writeAdmissionControllerPolicy(policyInterface kyvernov1.PolicyInterface) {
+ policyName := strings.ReplaceAll(policyInterface.GetName(), img.Name+"-", "")
outFile := img.getPolicyFile(policyName)
- _ = os.MkdirAll(filepath.Dir(outFile), 0750)
+ err := os.MkdirAll(filepath.Dir(outFile), 0750)
+ if err != nil {
+ log.WithError(err).Error("create dir failed")
+ return
+ }
f, err := os.Create(filepath.Clean(outFile))
if err != nil {
log.WithError(err).Error(fmt.Sprintf("create file %s failed", outFile))
+ return
+ }
+ var jsonBytes []byte
+ var yamlBytes []byte
+ jsonBytes, err = convertKyvernoPolicyInterfaceToJSON(policyInterface)
+ if err != nil {
+ log.WithError(err).Error("json marshal failed")
+ return
+ }
+ yamlBytes, err = yaml.JSONToYAML(jsonBytes)
+ if err != nil {
+ log.WithError(err).Error("yaml marshal failed")
+ return
+ }
+ if _, err := f.WriteString(string(yamlBytes)); err != nil {
+ log.WithError(err).Error("WriteString failed")
+ return
+ }
+ if err := f.Sync(); err != nil {
+ log.WithError(err).Error("file sync failed")
+ return
+ }
+ if err := f.Close(); err != nil {
+ log.WithError(err).Error("file close failed")
+ return
+ }
+ err = ReportAdmissionControllerRecord(outFile, string(policyInterface.GetSpec().ValidationFailureAction), policyInterface.GetAnnotations())
+ if err != nil {
+ log.WithError(err).Error("report admission controller record failed")
+ } else {
+ color.Green("created policy %s ...", outFile)
+ }
+}
+func writeGenericAdmissionControllerPolicy(policyInterface kyvernov1.PolicyInterface) {
+ policyName := policyInterface.GetName()
+ outFile := filepath.Join(options.OutDir, "genericKyvernoPolicies", policyName+".yaml")
+ err := os.MkdirAll(filepath.Dir(outFile), 0750)
+ if err != nil {
+ log.WithError(err).Error("create dir failed")
+ return
}
- arr, _ := json.Marshal(policy)
- yamlArr, _ := yaml.JSONToYAML(arr)
- if _, err := f.WriteString(string(yamlArr)); err != nil {
+ f, err := os.Create(filepath.Clean(outFile))
+ if err != nil {
+ log.WithError(err).Error(fmt.Sprintf("create file %s failed", outFile))
+ return
+ }
+ var jsonBytes []byte
+ var yamlBytes []byte
+ jsonBytes, err = convertKyvernoPolicyInterfaceToJSON(policyInterface)
+ if err != nil {
+ log.WithError(err).Error("json marshal failed")
+ return
+ }
+ yamlBytes, err = yaml.JSONToYAML(jsonBytes)
+ if err != nil {
+ log.WithError(err).Error("yaml marshal failed")
+ return
+ }
+ if _, err := f.WriteString(string(yamlBytes)); err != nil {
log.WithError(err).Error("WriteString failed")
+ return
}
if err := f.Sync(); err != nil {
log.WithError(err).Error("file sync failed")
+ return
}
if err := f.Close(); err != nil {
log.WithError(err).Error("file close failed")
+ return
+ }
+ err = ReportAdmissionControllerRecord(outFile, string(policyInterface.GetSpec().ValidationFailureAction), policyInterface.GetAnnotations())
+ if err != nil {
+ log.WithError(err).Error("report admission controller record failed")
+ } else {
+ color.Green("created policy %s ...", outFile)
}
- _ = ReportAdmissionControllerRecord(outFile, string(policy.Spec.ValidationFailureAction), policy.Annotations)
- color.Green("created policy %s ...", outFile)
}
func (img *ImageInfo) getPolicyFromImageInfo() {
diff --git a/recommend/policyTemplates.go b/recommend/policyTemplates.go
index b59527ec..b67e7f38 100644
--- a/recommend/policyTemplates.go
+++ b/recommend/policyTemplates.go
@@ -17,7 +17,6 @@ import (
"github.com/google/go-github/github"
kg "github.com/kubearmor/KubeArmor/KubeArmor/log"
pol "github.com/kubearmor/KubeArmor/pkg/KubeArmorController/api/security.kubearmor.com/v1"
- kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
log "github.com/sirupsen/logrus"
"sigs.k8s.io/yaml"
)
@@ -209,12 +208,9 @@ func updatePolicyRules(filePath string) error {
}
apiVersion := policy["apiVersion"].(string)
if strings.Contains(apiVersion, "kyverno") {
- var kyvernoPolicy kyvernov1.Policy
- err = yaml.Unmarshal(newYaml, &kyvernoPolicy)
- if err != nil {
- return err
- }
- ms.KyvernoPolicySpec = &kyvernoPolicy.Spec
+ // No need to add Kyverno policies to 'rules.yaml'
+ // Kyverno policies are fetched from discovery engine
+ continue
} else if strings.Contains(apiVersion, "kubearmor") {
var kubeArmorPolicy pol.KubeArmorPolicy
err = yaml.Unmarshal(newYaml, &kubeArmorPolicy)
diff --git a/recommend/recommend.go b/recommend/recommend.go
index ea78d38b..e6675562 100644
--- a/recommend/recommend.go
+++ b/recommend/recommend.go
@@ -165,6 +165,20 @@ func Recommend(c *k8s.Client, o Options) error {
}
}
+ recommendKyvernoPolicies := false
+ for _, policy := range options.Policy {
+ if policy == KyvernoPolicy {
+ recommendKyvernoPolicies = true
+ }
+ }
+
+ if recommendKyvernoPolicies {
+ err = recommendGenericAdmissionControllerPolicies()
+ if err != nil {
+ log.Error(err)
+ }
+ }
+
finalReport()
return nil
}
diff --git a/recommend/report.go b/recommend/report.go
index 17d2e779..1e52f28e 100644
--- a/recommend/report.go
+++ b/recommend/report.go
@@ -15,6 +15,16 @@ for every image {
for every policy {
ReportRecord()
}
+ for every dynamic_admission_controller_policy {
+ ReportAdmissionControllerRecord()
+ }
+ ReportSectEnd()
+}
+if recommend_generic_admission_controller_policies {
+ ReportStartGenericAdmissionControllerPolicies()
+ for every generic_admission_controller_policy {
+ ReportAdmissionControllerRecord()
+ }
ReportSectEnd()
}
ReportRender()
@@ -46,6 +56,17 @@ func ReportStart(img *ImageInfo) error {
return errors.New("unknown reporter type")
}
+// ReportStartGenericAdmissionControllerPolicies called once per generic admission controller policy at the start
+func ReportStartGenericAdmissionControllerPolicies() error {
+ switch v := Handler.(type) {
+ case HTMLReport:
+ return v.StartGenericAdmissionControllerPolicies()
+ case TextReport:
+ return v.StartGenericAdmissionControllerPolicies()
+ }
+ return errors.New("unknown reporter type")
+}
+
// ReportRecord called once per policy
func ReportRecord(ms MatchSpec, policyName string) error {
switch v := Handler.(type) {
@@ -58,23 +79,23 @@ func ReportRecord(ms MatchSpec, policyName string) error {
}
// ReportAdmissionControllerRecord called once per admission controller policy
-func ReportAdmissionControllerRecord(policyName, action string, annotations map[string]string) error {
+func ReportAdmissionControllerRecord(policyFilePath, action string, annotations map[string]string) error {
switch v := Handler.(type) {
case HTMLReport:
- return v.RecordAdmissionController(policyName, action, annotations)
+ return v.RecordAdmissionController(policyFilePath, action, annotations)
case TextReport:
- return v.RecordAdmissionController(policyName, action, annotations)
+ return v.RecordAdmissionController(policyFilePath, action, annotations)
}
return errors.New("unknown reporter type")
}
// ReportSectEnd called once per container image at the end
-func ReportSectEnd(img *ImageInfo) error {
+func ReportSectEnd() error {
switch v := Handler.(type) {
case HTMLReport:
- return v.SectionEnd(img)
+ return v.SectionEnd()
case TextReport:
- return v.SectionEnd(img)
+ return v.SectionEnd()
}
return errors.New("unknown reporter type")
}
diff --git a/recommend/report_html.go b/recommend/report_html.go
index efc46078..f5bdf371 100644
--- a/recommend/report_html.go
+++ b/recommend/report_html.go
@@ -13,6 +13,7 @@ import (
"strings"
"time"
+ "github.com/accuknox/auto-policy-discovery/src/types"
log "github.com/sirupsen/logrus"
"golang.org/x/text/cases"
"golang.org/x/text/language"
@@ -72,8 +73,9 @@ type HeaderInfo struct {
// SectionInfo Section information
type SectionInfo struct {
- HdrCols []Col
- ImgInfo []Info
+ HdrCols []Col
+ ImgInfo []Info
+ GenericAdmissionControllerPolicy bool
}
// NewHTMLReport instantiation on new html report
@@ -137,6 +139,21 @@ func (r HTMLReport) Start(img *ImageInfo) error {
return nil
}
+func (r HTMLReport) StartGenericAdmissionControllerPolicies() error {
+ secInfo := SectionInfo{
+ HdrCols: []Col{
+ {Name: "POLICY"},
+ {Name: "DESCRIPTION"},
+ {Name: "SEVERITY"},
+ {Name: "ACTION"},
+ {Name: "TAGS"},
+ },
+ GenericAdmissionControllerPolicy: true,
+ }
+ _ = r.section.Execute(r.outString, secInfo)
+ return nil
+}
+
// RecordInfo new row information in table
type RecordInfo struct {
RowID string
@@ -174,34 +191,33 @@ func (r HTMLReport) Record(ms MatchSpec, policyName string) error {
}
// RecordAdmissionController addition of new HTML table row for admission controller policies
-func (r HTMLReport) RecordAdmissionController(policyName, action string, annotations map[string]string) error {
+func (r HTMLReport) RecordAdmissionController(policyFilePath, action string, annotations map[string]string) error {
*r.RecordCnt = *r.RecordCnt + 1
- policy, err := os.ReadFile(filepath.Clean(policyName))
+ policy, err := os.ReadFile(filepath.Clean(policyFilePath))
if err != nil {
- log.WithError(err).Error(fmt.Sprintf("failed to read policy %s", policyName))
+ log.WithError(err).Error(fmt.Sprintf("failed to read policy %s", policyFilePath))
}
- policyName = policyName[strings.LastIndex(policyName, "/")+1:]
+ policyFilePath = policyFilePath[strings.LastIndex(policyFilePath, "/")+1:]
reci := RecordInfo{
RowID: fmt.Sprintf("row%d", *r.RecordCnt),
Rec: []Col{
- {Name: policyName},
- {Name: annotations["recommended-policies.kubearmor.io/description"]},
+ {Name: policyFilePath},
+ {Name: annotations[types.RecommendedPolicyTitleAnnotation]},
{Name: "-"},
{Name: cases.Title(language.English).String(action)},
- {Name: strings.Join(strings.Split(annotations["recommended-policies.kubearmor.io/tags"], ",")[:], "\n")},
+ {Name: strings.Join(strings.Split(annotations[types.RecommendedPolicyTagsAnnotation], ",")[:], "\n")},
},
Policy: string(policy),
PolicyType: "Kyverno Policy",
- Description: annotations["recommended-policies.kubearmor.io/description-detailed"],
+ Description: annotations[types.RecommendedPolicyDescriptionAnnotation],
// TODO: Figure out how to get the references, adding them to annotations would make them too long
Refs: []Ref{},
}
- _ = r.record.Execute(r.outString, reci)
- return nil
+ return r.record.Execute(r.outString, reci)
}
// SectionEnd end of section of the HTML table
-func (r HTMLReport) SectionEnd(img *ImageInfo) error {
+func (r HTMLReport) SectionEnd() error {
return r.sectend.Execute(r.outString, nil)
}
diff --git a/recommend/report_text.go b/recommend/report_text.go
index 58e52099..15dc3118 100644
--- a/recommend/report_text.go
+++ b/recommend/report_text.go
@@ -9,6 +9,7 @@ import (
"os"
"strings"
+ "github.com/accuknox/auto-policy-discovery/src/types"
"github.com/olekukonko/tablewriter"
log "github.com/sirupsen/logrus"
)
@@ -54,8 +55,20 @@ func (r TextReport) Start(img *ImageInfo) error {
return nil
}
+func (r TextReport) StartGenericAdmissionControllerPolicies() error {
+ t := tablewriter.NewWriter(r.outString)
+ t.SetBorder(false)
+ t.Rich([]string{"Generic Kyverno Policies"}, []tablewriter.Colors{{tablewriter.Bold}})
+ t.Render()
+
+ r.table.SetHeader([]string{"Policy", "Short Desc", "Severity", "Action", "Tags"})
+ r.table.SetAlignment(tablewriter.ALIGN_LEFT)
+ r.table.SetRowLine(true)
+ return nil
+}
+
// SectionEnd end of section of the text table
-func (r TextReport) SectionEnd(img *ImageInfo) error {
+func (r TextReport) SectionEnd() error {
r.table.Render()
r.table.ClearRows()
r.outString.WriteString("\n")
@@ -76,14 +89,14 @@ func (r TextReport) Record(ms MatchSpec, policyName string) error {
}
// RecordAdmissionController adds new row to table for admission controller policies
-func (r TextReport) RecordAdmissionController(policyName, action string, annotations map[string]string) error {
+func (r TextReport) RecordAdmissionController(policyFilePath, action string, annotations map[string]string) error {
var rec []string
- policyName = policyName[strings.LastIndex(policyName, "/")+1:]
- rec = append(rec, wrapPolicyName(policyName, 35))
- rec = append(rec, annotations["recommended-policies.kubearmor.io/description"])
+ policyFilePath = policyFilePath[strings.LastIndex(policyFilePath, "/")+1:]
+ rec = append(rec, wrapPolicyName(policyFilePath, 35))
+ rec = append(rec, annotations[types.RecommendedPolicyTitleAnnotation])
rec = append(rec, "-")
rec = append(rec, action)
- rec = append(rec, strings.Join(strings.Split(annotations["recommended-policies.kubearmor.io/tags"], ",")[:], "\n"))
+ rec = append(rec, strings.Join(strings.Split(annotations[types.RecommendedPolicyTagsAnnotation], ",")[:], "\n"))
r.table.Append(rec)
return nil
}