Skip to content

Commit

Permalink
Initial support for kyverno policies
Browse files Browse the repository at this point in the history
Signed-off-by: Mmadu Manasseh <[email protected]>
  • Loading branch information
MeNsaaH committed Dec 18, 2024
1 parent a404abb commit 53a514f
Show file tree
Hide file tree
Showing 11 changed files with 951 additions and 155 deletions.
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
earthly 0.8.15
golang 1.22.7
golang 1.23.4
golangci-lint 1.62.2
helm 3.16.3
helm-cr 1.6.1
Expand Down
2 changes: 1 addition & 1 deletion Tiltfile
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ k8s_resource(
port_forwards=['2345:2345', '8080:8080'],
resource_deps=[
# 'go-build',
'go-test',
# 'go-test',
'k8s:namespace',
'argocd',
'argocd-crds',
Expand Down
2 changes: 1 addition & 1 deletion charts/kubechecks/templates/clusterrole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ rules:
resources: ['applications', 'appprojects', 'applicationsets', 'services']
verbs: ['get', 'list', 'watch']
- apiGroups: [''] # The core API group, which is indicated by an empty string
resources: ['secrets']
resources: ['secrets', 'configmaps']
verbs: ['get', 'list', 'watch']
6 changes: 6 additions & 0 deletions cmd/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ var ControllerCmd = &cobra.Command{
log.Fatal().Err(err).Msg("failed to process schema locations")
}

log.Info().Strs("locations", cfg.KyvernoPoliciesLocation).Msg("processing kyverno policies locations")
if err = processLocations(ctx, ctr, cfg.KyvernoPoliciesLocation); err != nil {
log.Fatal().Err(err).Msg("failed to process kyverno policies locations")
}
log.Debug().Strs("locations", cfg.KyvernoPoliciesLocation).Msg("kyverno policies locations after processing")

processors, err := getProcessors(ctr)
if err != nil {
log.Fatal().Err(err).Msg("failed to create processors")
Expand Down
5 changes: 5 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ func init() {
stringFlag(flags, "replan-comment-msg", "comment message which re-triggers kubechecks on PR.",
newStringOpts().
withDefault("kubechecks again"))
boolFlag(flags, "enable-kyverno-checks", "Enable kyverno policy checks.")
stringFlag(flags, "kyverno-policies-location", "Sets kyverno policy locations to be used for every check request. This is a git url in either git or http(s) format.")
stringSliceFlag(flags, "kyverno-policies-paths", "Sets the paths inside the kyverno-policies-location that contains the policies. Default to root of the repository.",
newStringSliceOpts().
withDefault([]string{"."}))

panicIfError(viper.BindPFlags(flags))
setupLogOutput()
Expand Down
264 changes: 218 additions & 46 deletions go.mod

Large diffs are not rendered by default.

721 changes: 616 additions & 105 deletions go.sum

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion localdev/kubechecks/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,18 @@ configMap:
# KUBECHECKS_SCHEMAS_LOCATION: https://github.com/zapier/kubecheck-schemas.git
KUBECHECKS_TIDY_OUTDATED_COMMENTS_MODE: "delete"
KUBECHECKS_ENABLE_CONFTEST: "false"
KUBECHECKS_ENABLE_KYVERNO_CHECKS: "true"
KUBECHECKS_KYVERNO_POLICIES_LOCATION: "https://gitlab.com/zapier/team-sre/service-kyverno.git"
KUBECHECKS_KYVERNO_POLICIES_PATHS: "argocd/production/templates/checks"
GRPC_ENFORCE_ALPN_ENABLED: false


deployment:
annotations:
reloader.stakater.com/auto: "true"

image:
pullPolicy: Never
pullPolicy: IfNotPresent
name: "kubechecks"
tag: ""

Expand Down
12 changes: 12 additions & 0 deletions pkg/checks/kyverno/check.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package kyverno

import (
"context"

"github.com/zapier/kubechecks/pkg/checks"
"github.com/zapier/kubechecks/pkg/msg"
)

func Check(ctx context.Context, request checks.Request) (msg.Result, error) {
return kyvernoValidate(ctx, request.Container, request.AppName, request.KubernetesVersion, request.YamlManifests)
}
82 changes: 82 additions & 0 deletions pkg/checks/kyverno/kyverno.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package kyverno

import (
"context"
"fmt"
"os"
"path/filepath"
"strings"

"github.com/rs/zerolog/log"
"github.com/zapier/kubechecks/pkg"
"github.com/zapier/kubechecks/pkg/container"
"github.com/zapier/kubechecks/pkg/msg"
"go.opentelemetry.io/otel"

"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/commands/apply"
)

var tracer = otel.Tracer("pkg/checks/kyverno")

func kyvernoValidate(ctx context.Context, ctr container.Container, appName, targetKubernetesVersion string, appManifests []string) (msg.Result, error) {
_, span := tracer.Start(ctx, "KyvernoValidate")
defer span.End()

tempFile, err := os.CreateTemp("/tmp", "appManifests-*.yaml")
if err != nil {
return msg.Result{}, err
}
defer os.Remove(tempFile.Name())

for _, manifest := range appManifests {
if _, err := tempFile.WriteString(manifest + "\n"); err != nil {
return msg.Result{}, err
}
}

if err := tempFile.Close(); err != nil {
return msg.Result{}, err
}

// This calls the kyverno apply -r <RESOURCE_FILE> <POLICY LOCATIONS ...> command
applyCommand := apply.Command()
applyCommand.SetArgs(
append(
getPoliciesLocations(ctr),
[]string{"-r", tempFile.Name()}...))
var output strings.Builder
applyCommand.SetOutput(&output)
if err := applyCommand.Execute(); err != nil {
return msg.Result{}, err
}
log.Info().Msg(output.String())

var cr msg.Result
if output.Len() == 0 {
cr.State = pkg.StateWarning
} else {
cr.State = pkg.StateSuccess
}

cr.Summary = "<b>Show kyverno report:</b>"
cr.Details = fmt.Sprintf(">Kyverno Policy Report \n\n%s", output.String())

return cr, nil
}

func getPoliciesLocations(ctr container.Container) []string {
cfg := ctr.Config

// schemas configured globally
var locations []string

for _, location := range cfg.KyvernoPoliciesLocation {
for _, path := range cfg.KyvernoPoliciesPaths {
locations = append(locations, filepath.Join(location, path))
}
}

log.Debug().Strs("locations", locations).Msg("processed kyverno policies locations")

return locations
}
4 changes: 4 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ type ServerConfig struct {
// -- preupgrade
EnablePreupgrade bool `mapstructure:"enable-preupgrade"`
WorstPreupgradeState pkg.CommitState `mapstructure:"worst-preupgrade-state"`
// -- kyverno
EnableKyvernoChecks bool `mapstructure:"enable-kyverno-checks"`
KyvernoPoliciesLocation []string `mapstructure:"kyverno-policies-location"`
KyvernoPoliciesPaths []string `mapstructure:"kyverno-policies-paths"`

// misc
FallbackK8sVersion string `mapstructure:"fallback-k8s-version"`
Expand Down

0 comments on commit 53a514f

Please sign in to comment.