Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: initial kyverno support #1200

Merged
merged 23 commits into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
85df788
refresh fork
ronaldpetty Jul 6, 2024
17e3c79
let out, wasn't sure it was needed, but seems it might be in CI pipeline
ronaldpetty Jul 16, 2024
7012aa3
chore(deps): update docker/setup-buildx-action digest to 4fd8129 (#1173)
renovate[bot] Jul 8, 2024
7ea6132
fix(deps): update module buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosy…
renovate[bot] Jul 8, 2024
b0e91b6
chore(deps): update anchore/sbom-action action to v0.16.0 (#1146)
renovate[bot] Jul 8, 2024
186e3e1
fix(deps): update module google.golang.org/grpc to v1.64.1 [security]…
renovate[bot] Jul 10, 2024
ab7d1a1
fix(deps): update module github.com/mittwald/go-helm-client to v0.12.…
renovate[bot] Jul 10, 2024
57801a4
feat: add custom http headers to openai related api backends (#1174)
arbreezy Jul 10, 2024
35f8183
chore(main): release 0.3.38 (#1165)
github-actions[bot] Jul 10, 2024
886a887
chore(deps): update anchore/sbom-action action to v0.16.1 (#1179)
renovate[bot] Jul 11, 2024
c37a94c
chore(deps): update actions/setup-go digest to 0a12ed9 (#1182)
renovate[bot] Jul 11, 2024
b977ff0
ci: release to krew index as kubectl-gpt (#1100)
miguelvr Jul 11, 2024
a2d659d
fix(deps): update k8s.io/utils digest to 18e509b (#1183)
renovate[bot] Jul 11, 2024
2680b20
fix(deps): update module github.com/prometheus/prometheus to v0.53.1 …
renovate[bot] Jul 11, 2024
2fbb7b2
fix(deps): update module github.com/ibm/watsonx-go to v1.0.1 (#1187)
renovate[bot] Jul 11, 2024
75351c5
feat: skip k3s node type EtcdIsVoter (#1167)
yankay Jul 12, 2024
88a4dab
feat: fix the custom-analysis printing (#1195)
AlexsJones Jul 15, 2024
43bba70
chore(deps): pin goreleaser/goreleaser-action action to 286f3b1 (#1171)
renovate[bot] Jul 15, 2024
d754600
fix(deps): update module buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go to…
renovate[bot] Jul 15, 2024
8d78ec1
chore(deps): update actions/upload-artifact digest to 0b2256b (#1175)
renovate[bot] Jul 15, 2024
c272fbf
Update pkg/integration/kyverno/kyverno.go
ronaldpetty Jul 17, 2024
7a164a4
remove unused function
ronaldpetty Jul 17, 2024
412fdd1
Merge branch 'main' into kyverno
ronaldpetty Jul 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ require (
github.com/google/generative-ai-go v0.11.0
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0
github.com/hupe1980/go-huggingface v0.0.15
github.com/kyverno/policy-reporter-kyverno-plugin v1.6.3
github.com/olekukonko/tablewriter v0.0.5
github.com/oracle/oci-go-sdk/v65 v65.65.1
github.com/prometheus/prometheus v0.53.1
Expand Down Expand Up @@ -98,6 +99,7 @@ require (
github.com/prometheus/common/sigv4 v0.1.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/segmentio/fasthash v1.0.3 // indirect
github.com/sony/gobreaker v0.5.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2006,6 +2006,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/kyverno/policy-reporter-kyverno-plugin v1.6.3 h1:wr6Hglqa9Lw31nMnypXGJb+ujK3vmxacC/lJMZkp5No=
github.com/kyverno/policy-reporter-kyverno-plugin v1.6.3/go.mod h1:ms0YASmim7qtJresYsGuhkpCtQLWQIEYFA9ftOu4oQc=
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw=
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o=
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk=
Expand Down Expand Up @@ -2221,6 +2223,8 @@ github.com/scaleway/scaleway-sdk-go v1.0.0-beta.27 h1:yGAraK1uUjlhSXgNMIy8o/J4LF
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.27/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg=
github.com/schollz/progressbar/v3 v3.14.2 h1:EducH6uNLIWsr560zSV1KrTeUb/wZGAHqyMFIEa99ks=
github.com/schollz/progressbar/v3 v3.14.2/go.mod h1:aQAZQnhF4JGFtRJiw/eobaXpsqpVQAftEQ+hLGXaRc4=
github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM=
github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY=
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
Expand Down
12 changes: 12 additions & 0 deletions pkg/ai/prompts.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ const (
- Containers:
- {list of container names}
`

kyverno_prompt = `Simplify the following Kyverno warnings message delimited by triple dashes written in --- %s --- language; --- %s ---.
Provide the most probable solution as a kubectl command.

Write the output in the following format, for the solution, only show the kubectl command:

Error: {Explain error here}

Solution: {kubectl command}
`
)

var PromptMap = map[string]string{
Expand All @@ -56,4 +66,6 @@ var PromptMap = map[string]string{
"ConfigAuditReport": trivy_conf_prompt,
"PrometheusConfigValidate": prom_conf_prompt,
"PrometheusConfigRelabelReport": prom_relabel_prompt,
"PolicyReport": kyverno_prompt,
"ClusterPolicyReport": kyverno_prompt,
}
9 changes: 6 additions & 3 deletions pkg/common/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/k8sgpt-ai/k8sgpt/pkg/ai"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
keda "github.com/kedacore/keda/v2/apis/keda/v1alpha1"
kyverno "github.com/kyverno/policy-reporter-kyverno-plugin/pkg/crd/api/policyreport/v1alpha2"
regv1 "k8s.io/api/admissionregistration/v1"
appsv1 "k8s.io/api/apps/v1"
autov1 "k8s.io/api/autoscaling/v1"
Expand Down Expand Up @@ -63,9 +64,11 @@ type PreAnalysis struct {
Gateway gtwapi.Gateway
HTTPRoute gtwapi.HTTPRoute
// Integrations
ScaledObject keda.ScaledObject
TrivyVulnerabilityReport trivy.VulnerabilityReport
TrivyConfigAuditReport trivy.ConfigAuditReport
ScaledObject keda.ScaledObject
TrivyVulnerabilityReport trivy.VulnerabilityReport
TrivyConfigAuditReport trivy.ConfigAuditReport
KyvernoPolicyReport kyverno.PolicyReport
KyvernoClusterPolicyReport kyverno.ClusterPolicyReport
}

type Result struct {
Expand Down
2 changes: 2 additions & 0 deletions pkg/integration/integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"fmt"

"github.com/k8sgpt-ai/k8sgpt/pkg/integration/aws"
"github.com/k8sgpt-ai/k8sgpt/pkg/integration/kyverno"

"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/integration/keda"
Expand Down Expand Up @@ -52,6 +53,7 @@ var integrations = map[string]IIntegration{
"prometheus": prometheus.NewPrometheus(),
"aws": aws.NewAWS(),
"keda": keda.NewKeda(),
"kyverno": kyverno.NewKyverno(),
}

func NewIntegration() *Integration {
Expand Down
162 changes: 162 additions & 0 deletions pkg/integration/kyverno/analyzer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/*
Copyright 2023 The K8sGPT Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package kyverno

import (
"fmt"

ctrl "sigs.k8s.io/controller-runtime/pkg/client"

"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/util"

"github.com/kyverno/policy-reporter-kyverno-plugin/pkg/crd/api/policyreport/v1alpha2"
)

// "github.com/kyverno/policy-reporter-kyverno-plugin/pkg/crd/api/policyreport/v1alpha2"

type KyvernoAnalyzer struct {
policyReportAnalysis bool
clusterReportAnalysis bool
}

func (KyvernoAnalyzer) analyzePolicyReports(a common.Analyzer) ([]common.Result, error) {
result := &v1alpha2.PolicyReportList{}
client := a.Client.CtrlClient

err := v1alpha2.AddToScheme(client.Scheme())
if err != nil {
return nil, err
}
if err := client.List(a.Context, result, &ctrl.ListOptions{}); err != nil {
return nil, err
}

// Find criticals and get CVE
var preAnalysis = map[string]common.PreAnalysis{}

for _, report := range result.Items {

// For each pod there may be multiple vulnerabilities
var failures []common.Failure
for _, vuln := range report.Results {
if vuln.Result == "fail" {
// get the vulnerability ID
// get the vulnerability description
failures = append(failures, common.Failure{
Text: fmt.Sprintf("policy failure: %s (message: %s)", vuln.Policy, vuln.Message),
Sensitive: []common.Sensitive{},
})
}
}
if len(failures) > 0 {
preAnalysis[fmt.Sprintf("%s/%s", report.Namespace,
report.Name)] = common.PreAnalysis{
KyvernoPolicyReport: report,
FailureDetails: failures,
}
}
}

for key, value := range preAnalysis {
var currentAnalysis = common.Result{
Kind: "PolicyReport",
Name: key,
Error: value.FailureDetails,
}

parent, _ := util.GetParent(a.Client, value.KyvernoPolicyReport.ObjectMeta)
currentAnalysis.ParentObject = parent
a.Results = append(a.Results, currentAnalysis)
}

return a.Results, nil

}

func (t KyvernoAnalyzer) analyzeClusterPolicyReports(a common.Analyzer) ([]common.Result, error) {
result := &v1alpha2.ClusterPolicyReportList{}
client := a.Client.CtrlClient

err := v1alpha2.AddToScheme(client.Scheme())
if err != nil {
return nil, err
}
if err := client.List(a.Context, result, &ctrl.ListOptions{}); err != nil {
return nil, err
}

// Find criticals and get CVE
var preAnalysis = map[string]common.PreAnalysis{}

for _, report := range result.Items {

// For each pod there may be multiple vulnerabilities
var failures []common.Failure
for _, vuln := range report.Results {
if vuln.Severity == "CRITICAL" {
// get the vulnerability ID
// get the vulnerability description
failures = append(failures, common.Failure{
Text: fmt.Sprintf("critical Vulnerability found ID: %s (learn more at: %s)", vuln.ID, vuln.Source),
Sensitive: []common.Sensitive{},
})
}
}
if len(failures) > 0 {
preAnalysis[fmt.Sprintf("%s/%s", report.Namespace,
report.Name)] = common.PreAnalysis{
KyvernoClusterPolicyReport: report,
FailureDetails: failures,
}
}
}

for key, value := range preAnalysis {
var currentAnalysis = common.Result{
Kind: "ClusterPolicyReport",
Name: key,
Error: value.FailureDetails,
}

parent, _ := util.GetParent(a.Client, value.KyvernoClusterPolicyReport.ObjectMeta)
currentAnalysis.ParentObject = parent
a.Results = append(a.Results, currentAnalysis)
}

return a.Results, nil
}

func (t KyvernoAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {

if t.policyReportAnalysis {
common := make([]common.Result, 0)
vresult, err := t.analyzePolicyReports(a)
if err != nil {
return nil, err
}
common = append(common, vresult...)
return common, nil
}
if t.clusterReportAnalysis {
common := make([]common.Result, 0)
cresult, err := t.analyzeClusterPolicyReports(a)
if err != nil {
return nil, err
}
common = append(common, cresult...)
return common, nil
}
return make([]common.Result, 0), nil
}
117 changes: 117 additions & 0 deletions pkg/integration/kyverno/kyverno.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
Copyright 2023 The K8sGPT Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package kyverno

import (
"os"

"github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/spf13/viper"
)

type Kyverno struct{}

func NewKyverno() *Kyverno {
return &Kyverno{}
}

func (k *Kyverno) GetAnalyzerName() []string {
return []string{
//from wgpolicyk8s.io/v1alpha2
"PolicyReport",
"ClusterPolicyReport",
}
}

func (k *Kyverno) OwnsAnalyzer(analyzer string) bool {

for _, a := range k.GetAnalyzerName() {
if analyzer == a {
return true
}
}
return false
}

func (k *Kyverno) isDeployed() bool {
// check if wgpolicyk8s apigroup is available as a marker if new policy resource available is installed on the cluster
kubecontext := viper.GetString("kubecontext")
kubeconfig := viper.GetString("kubeconfig")
client, err := kubernetes.NewClient(kubecontext, kubeconfig)
if err != nil {
// TODO: better error handling
color.Red("Error initialising kubernetes client: %v", err)
os.Exit(1)
}
groups, _, err := client.Client.Discovery().ServerGroupsAndResources()
if err != nil {
// TODO: better error handling
color.Red("Error initialising discovery client: %v", err)
os.Exit(1)
}

for _, group := range groups {
if group.Name == "kyverno.io" {
return true
}
}

return false
}

func (k *Kyverno) isFilterActive() bool {
activeFilters := viper.GetStringSlice("active_filters")

for _, filter := range k.GetAnalyzerName() {
for _, af := range activeFilters {
if af == filter {
return true
}
}
}

return false
}

func (k *Kyverno) IsActivate() bool {
if k.isFilterActive() && k.isDeployed() {
return true
} else {
return false
}
}

func (k *Kyverno) AddAnalyzer(mergedMap *map[string]common.IAnalyzer) {

(*mergedMap)["PolicyReport"] = &KyvernoAnalyzer{
policyReportAnalysis: true,
}
(*mergedMap)["ClusterPolicyReport"] = &KyvernoAnalyzer{
clusterReportAnalysis: true,
}
}

func (k *Kyverno) Deploy(namespace string) error {
return nil
}

func (k *Kyverno) UnDeploy(_ string) error {
return nil
}

func (t *Kyverno) GetNamespace() (string, error) {
return "", nil
}
Loading