Skip to content

Commit

Permalink
implement exception controlls
Browse files Browse the repository at this point in the history
Signed-off-by: Frank Jogeleit <[email protected]>
  • Loading branch information
Frank Jogeleit committed Apr 3, 2024
1 parent e8de40b commit 430ebb6
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 16 deletions.
8 changes: 4 additions & 4 deletions plugins/kyverno/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ go 1.22
replace github.com/kyverno/policy-reporter-plugins/sdk/api v0.0.0 => ../../sdk/api

require (
github.com/gin-contrib/gzip v0.0.6
github.com/gin-contrib/gzip v1.0.0
github.com/gin-contrib/pprof v1.4.0
github.com/gin-contrib/zap v1.1.0
github.com/gin-contrib/zap v1.1.1
github.com/gin-gonic/gin v1.9.1
github.com/itchyny/json2yaml v0.1.4
github.com/kyverno/policy-reporter-plugins/sdk/api v0.0.0
Expand Down Expand Up @@ -79,7 +79,7 @@ require (
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/arch v0.7.0 // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/exp v0.0.0-20240318143956-a85f2c67cd81 // indirect
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect
golang.org/x/oauth2 v0.18.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/term v0.18.0 // indirect
Expand All @@ -91,7 +91,7 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/component-base v0.29.3 // indirect
k8s.io/klog/v2 v2.120.1 // indirect
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
k8s.io/kube-openapi v0.0.0-20240322212309-b815d8309940 // indirect
k8s.io/utils v0.0.0-20240310230437-4693a0247e57 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
Expand Down
8 changes: 8 additions & 0 deletions plugins/kyverno/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,16 @@ github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uq
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4=
github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk=
github.com/gin-contrib/gzip v1.0.0 h1:UKN586Po/92IDX6ie5CWLgMI81obiIp5nSP85T3wlTk=
github.com/gin-contrib/gzip v1.0.0/go.mod h1:CtG7tQrPB3vIBo6Gat9FVUsis+1emjvQqd66ME5TdnE=
github.com/gin-contrib/pprof v1.4.0 h1:XxiBSf5jWZ5i16lNOPbMTVdgHBdhfGRD5PZ1LWazzvg=
github.com/gin-contrib/pprof v1.4.0/go.mod h1:RrehPJasUVBPK6yTUwOl8/NP6i0vbUgmxtis+Z5KE90=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-contrib/zap v1.1.0 h1:GWzL9+zmK8OJdiycaK2SK1/D3SZIYpieJDD0QCNAU1o=
github.com/gin-contrib/zap v1.1.0/go.mod h1:KzROP9rAL7ofFd1P8lx7Oo2lerwPWNL5vv4f6U/mAk8=
github.com/gin-contrib/zap v1.1.1 h1:DDyIF9YQorl3gZzAabIowRywHJuohDfiLnhwvWKl6SY=
github.com/gin-contrib/zap v1.1.1/go.mod h1:YW8KOko2kYLy8g6k9YgVNTj7SIcrUEzYiAd9IjiBPs0=
github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
Expand Down Expand Up @@ -208,6 +212,8 @@ golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/exp v0.0.0-20240318143956-a85f2c67cd81 h1:6R2FC06FonbXQ8pK11/PDFY6N6LWlf9KlzibaCapmqc=
golang.org/x/exp v0.0.0-20240318143956-a85f2c67cd81/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ=
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw=
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
Expand Down Expand Up @@ -301,6 +307,8 @@ k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
k8s.io/kube-openapi v0.0.0-20240322212309-b815d8309940 h1:qVoMaQV5t62UUvHe16Q3eb2c5HPzLHYzsi0Tu/xLndo=
k8s.io/kube-openapi v0.0.0-20240322212309-b815d8309940/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
k8s.io/pod-security-admission v0.29.3 h1:9/8Fcewcm/uxU6cNjBLy/+0FkxyWXpnXwDz8AQkWLuU=
k8s.io/pod-security-admission v0.29.3/go.mod h1:tipz/v8IXwAPKS5J4FEMAYBVhMfmSWs8/03Hwup+Po4=
k8s.io/utils v0.0.0-20240310230437-4693a0247e57 h1:gbqbevonBh57eILzModw6mrkbwM0gQBEuevE/AaBsHY=
Expand Down
6 changes: 6 additions & 0 deletions plugins/kyverno/pkg/kubernetes/kyverno/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ import (
"gopkg.in/yaml.v2"
)

type Control struct {
ID string
Name string
Images []string
}

func mapContent(policy map[string]any) string {
if policy == nil {
return ""
Expand Down
72 changes: 60 additions & 12 deletions plugins/kyverno/pkg/server/v1/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import (
"encoding/json"
"fmt"
"net/http"
"regexp"
"strings"

"github.com/gin-gonic/gin"
"github.com/itchyny/json2yaml"
"go.uber.org/zap"
k8serror "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

Expand Down Expand Up @@ -81,42 +83,70 @@ func (h *APIHandler) Exception(ctx *gin.Context) {
ctx.AbortWithError(http.StatusNotFound, err)
}

var rules []string
var rules []api.ExceptionRule

if policy.GetSpec() != nil {
rules = utils.Map(policy.GetSpec().Rules, func(rule v1.Rule) string {
return rule.Name
rules = utils.Map(policy.GetSpec().Rules, func(rule v1.Rule) api.ExceptionRule {
return api.ExceptionRule{Name: rule.Name}
})
}

if policy.GetStatus() != nil {
rules = append(rules, utils.Map(policy.GetStatus().Autogen.Rules, func(rule v1.Rule) string {
return rule.Name
rules = append(rules, utils.Map(policy.GetStatus().Autogen.Rules, func(rule v1.Rule) api.ExceptionRule {
return api.ExceptionRule{Name: rule.Name}
})...)
}

request.Policies[i].Rules = rules
}
}

pssList := make([]v1.PodSecurityStandard, 0)

kinds := []string{request.Resource.Kind}
if utils.Contains(ControllerKinds, request.Resource.Kind) {
kinds = append(kinds, "Pod")

for i, policy := range request.Policies {
for _, rule := range policy.Rules {
if strings.HasPrefix(rule, "autogen-cronjob-") {
if strings.HasPrefix(rule.Name, "autogen-cronjob-") {
request.Policies[i].Rules = append(
policy.Rules,
strings.Replace(rule, "autogen-cronjob-", "autogen-", 1),
strings.TrimPrefix(rule, "autogen-cronjob-"),
api.ExceptionRule{Name: strings.Replace(rule.Name, "autogen-cronjob-", "autogen-", 1)},
api.ExceptionRule{Name: strings.TrimPrefix(rule.Name, "autogen-cronjob-")},
)
} else if strings.HasPrefix(rule, "autogen-") {
} else if strings.HasPrefix(rule.Name, "autogen-") {
request.Policies[i].Rules = append(
policy.Rules,
strings.TrimPrefix(rule, "autogen-"),
api.ExceptionRule{Name: strings.TrimPrefix(rule.Name, "autogen-")},
)
}

if cl, ok := rule.Props["controlsJSON"]; ok {
var controls []kyverno.Control
err := json.Unmarshal([]byte(cl), &controls)
if err != nil {
zap.L().Error("failed to unmarshal control", zap.Error(err), zap.String("control", cl))
continue
}

for _, c := range controls {
pss := v1.PodSecurityStandard{
ControlName: c.Name,
}
if c.Images != nil {
pss.Images = wildcardTagOrDigest(c.Images)
}
pssList = append(pssList, pss)
}
} else if cl, ok := rule.Props["controls"]; ok {
controls := strings.Split(cl, ",")
for _, c := range controls {
pssList = append(pssList, v1.PodSecurityStandard{
ControlName: c,
})
}
}
}
}
}
Expand All @@ -133,7 +163,9 @@ func (h *APIHandler) Exception(ctx *gin.Context) {
for _, p := range request.Policies {
exPolicies = append(exPolicies, v2beta1.Exception{
PolicyName: p.Name,
RuleNames: p.Rules,
RuleNames: utils.Map(p.Rules, func(rule api.ExceptionRule) string {
return rule.Name
}),
})
}

Expand All @@ -159,6 +191,7 @@ func (h *APIHandler) Exception(ctx *gin.Context) {
},
},
},
PodSecurity: pssList,
},
}

Expand All @@ -171,8 +204,14 @@ func (h *APIHandler) Exception(ctx *gin.Context) {
return
}

minVersion := "1.11"
if len(exception.Spec.PodSecurity) > 0 {
minVersion = "1.12"
}

ctx.JSON(http.StatusOK, api.ExceptionResponse{
Resource: output.String(),
MinVersion: minVersion,
Resource: output.String(),
})
}

Expand All @@ -185,3 +224,12 @@ func WithAPI(client kyverno.Client, coreAPI *core.Client) server.ServerOption {
return s.Register("api", NewHandler(client, coreAPI))
}
}

var regexpTagOrDigest = regexp.MustCompile(":.*|@.*")

func wildcardTagOrDigest(images []string) []string {
for i, s := range images {
images[i] = regexpTagOrDigest.ReplaceAllString(s, "*")
}
return images
}

0 comments on commit 430ebb6

Please sign in to comment.