1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-07 00:17:13 +00:00
kyverno/pkg/policyreport/policyreport.go
2020-08-26 18:50:38 +05:30

288 lines
8.8 KiB
Go
Executable file

package policyreport
import (
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
policyreportv1alpha1 "github.com/nirmata/kyverno/pkg/api/policyreport/v1alpha1"
client "github.com/nirmata/kyverno/pkg/dclient"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
"sync"
)
type PolicyReport struct {
report *policyreportv1alpha1.PolicyReport
clusterReport *policyreportv1alpha1.ClusterPolicyReport
violation *kyverno.PolicyViolationTemplate
k8sClient *client.Client
mux sync.Mutex
}
func NewPolicyReport(report *policyreportv1alpha1.PolicyReport, clusterReport *policyreportv1alpha1.ClusterPolicyReport, violation *kyverno.PolicyViolationTemplate, client *client.Client) *PolicyReport {
return &PolicyReport{
report: report,
clusterReport: clusterReport,
violation: violation,
k8sClient: client,
}
}
// RemovePolicyViolation
func (p *PolicyReport) RemovePolicyViolation(name string, pvInfo []Info) *policyreportv1alpha1.PolicyReport {
defer func() {
p.mux.Unlock()
}()
p.mux.Lock()
if len(pvInfo) > 0 {
for _, info := range pvInfo {
for j, v := range pvInfo[0].Rules {
for i, result := range p.report.Results {
if result.Resource.Name == info.Resource.GetName() && result.Policy == info.PolicyName && result.Rule == v.Name {
_, err := p.k8sClient.GetResource(result.Resource.APIVersion, result.Resource.Kind, result.Resource.Namespace, result.Resource.Name)
if err != nil {
if errors.IsNotFound(err) {
p.report.Results = append(p.report.Results[:i], p.report.Results[i+1:]...)
p.DecreaseCount(string(result.Status), "NAMESPACE")
}
} else {
if v.Check != string(result.Status) {
result.Message = v.Message
p.DecreaseCount(string(result.Status), "NAMESPACE")
result.Status = policyreportv1alpha1.PolicyStatus(v.Check)
p.IncreaseCount(string(v.Check), "NAMESPACE")
}
info.Rules = append(info.Rules[:j], info.Rules[j+1:]...)
}
}
}
}
}
} else {
for i, result := range p.report.Results {
if result.Policy == name {
p.report.Results = append(p.report.Results[:i], p.report.Results[i+1:]...)
p.DecreaseCount(string(result.Status), "NAMESPACE")
}
}
}
return p.report
}
//RemoveClusterPolicyViolation
func (p *PolicyReport) RemoveClusterPolicyViolation(name string, pvInfo []Info) *policyreportv1alpha1.ClusterPolicyReport {
defer func() {
p.mux.Unlock()
}()
p.mux.Lock()
if len(pvInfo) > 0 {
for _, info := range pvInfo {
for j, v := range info.Rules {
for i, result := range p.clusterReport.Results {
if result.Resource.Name == info.Resource.GetName() && result.Policy == info.PolicyName && result.Rule == v.Name {
_, err := p.k8sClient.GetResource(result.Resource.APIVersion, result.Resource.Kind, result.Resource.Namespace, result.Resource.Name)
if err != nil {
if errors.IsNotFound(err) {
p.report.Results = append(p.report.Results[:i], p.report.Results[i+1:]...)
p.DecreaseCount(string(result.Status), "CLUSTER")
}
} else {
if v.Check != string(result.Status) {
result.Message = v.Message
p.DecreaseCount(string(result.Status), "CLUSTER")
result.Status = policyreportv1alpha1.PolicyStatus(v.Check)
p.IncreaseCount(string(v.Check), "CLUSTER")
}
info.Rules = append(info.Rules[:j], info.Rules[j+1:]...)
}
}
}
}
}
} else {
for i, result := range p.clusterReport.Results {
if result.Policy == name {
p.clusterReport.Results = append(p.clusterReport.Results[:i], p.clusterReport.Results[i+1:]...)
p.DecreaseCount(string(result.Status), "CLUSTER")
}
}
}
return p.clusterReport
}
// CreatePolicyViolationToPolicyReport
func (p *PolicyReport) CreatePolicyViolationToPolicyReport() *policyreportv1alpha1.PolicyReport {
defer func() {
p.mux.Unlock()
}()
p.mux.Lock()
for _, result := range p.report.Results {
for i, rule := range p.violation.Spec.ViolatedRules {
if result.Policy == p.violation.Spec.Policy && result.Rule == rule.Name && result.Resource.Name == p.violation.Spec.Name {
_, err := p.k8sClient.GetResource(result.Resource.APIVersion, result.Resource.Kind, result.Resource.Namespace, result.Resource.Name)
if err != nil {
if errors.IsNotFound(err) {
p.report.Results = append(p.report.Results[:i], p.report.Results[i+1:]...)
}
} else {
if rule.Check != string(result.Status) {
p.DecreaseCount(string(result.Status), "NAMESPACE")
p.IncreaseCount(rule.Check, "NAMESPACE")
result.Message = rule.Message
}
p.violation.Spec.ViolatedRules = append(p.violation.Spec.ViolatedRules[:i], p.violation.Spec.ViolatedRules[i+1:]...)
}
}
}
}
for _, rule := range p.violation.Spec.ViolatedRules {
_, err := p.k8sClient.GetResource(p.violation.Spec.APIVersion, p.violation.Spec.Kind, p.violation.Spec.Namespace, p.violation.Spec.Name)
if err != nil {
if errors.IsNotFound(err) {
continue
}
} else {
result := &policyreportv1alpha1.PolicyReportResult{
Policy: p.violation.Spec.Policy,
Rule: rule.Name,
Message: rule.Message,
Status: policyreportv1alpha1.PolicyStatus(rule.Check),
Resource: &corev1.ObjectReference{
Kind: p.violation.Spec.Kind,
Namespace: p.violation.Spec.Namespace,
APIVersion: p.violation.Spec.APIVersion,
Name: p.violation.Spec.Name,
},
}
p.IncreaseCount(rule.Check, "NAMESPACE")
p.report.Results = append(p.report.Results, result)
}
}
return p.report
}
// ClusterPolicyViolationsToClusterPolicyReport
func (p *PolicyReport) CreateClusterPolicyViolationsToClusterPolicyReport() *policyreportv1alpha1.ClusterPolicyReport {
defer func() {
p.mux.Unlock()
}()
p.mux.Lock()
for _, result := range p.clusterReport.Results {
for i, rule := range p.violation.Spec.ViolatedRules {
if result.Policy == p.violation.Spec.Policy && result.Rule == rule.Name && result.Resource.Name == p.violation.Spec.Name {
_, err := p.k8sClient.GetResource(result.Resource.APIVersion, result.Resource.Kind, result.Resource.Namespace, result.Resource.Name)
if err != nil {
if errors.IsNotFound(err) {
p.clusterReport.Results = append(p.clusterReport.Results[:i], p.clusterReport.Results[i+1:]...)
continue
}
} else {
if rule.Check != string(result.Status) {
result.Message = rule.Message
p.DecreaseCount(string(result.Status), "CLUSTER")
p.IncreaseCount(rule.Check, "CLUSTER")
}
p.violation.Spec.ViolatedRules = append(p.violation.Spec.ViolatedRules[:i], p.violation.Spec.ViolatedRules[i+1:]...)
}
}
}
}
for _, rule := range p.violation.Spec.ViolatedRules {
_, err := p.k8sClient.GetResource(p.violation.Spec.APIVersion, p.violation.Spec.Kind, p.violation.Spec.Namespace, p.violation.Spec.Name)
if err != nil {
if errors.IsNotFound(err) {
continue
}
} else {
result := &policyreportv1alpha1.PolicyReportResult{
Policy: p.violation.Spec.Policy,
Rule: rule.Name,
Message: rule.Message,
Status: policyreportv1alpha1.PolicyStatus(rule.Check),
Resource: &corev1.ObjectReference{
Kind: p.violation.Spec.Kind,
Namespace: p.violation.Spec.Namespace,
APIVersion: p.violation.Spec.APIVersion,
Name: p.violation.Spec.Name,
},
}
p.IncreaseCount(rule.Check, "CLUSTER")
p.clusterReport.Results = append(p.clusterReport.Results, result)
}
}
return p.clusterReport
}
func (p *PolicyReport) DecreaseCount(status string, scope string) {
if scope == "CLUSTER" {
switch status {
case "Pass":
if p.clusterReport.Summary.Pass--; p.clusterReport.Summary.Pass < 0 {
p.clusterReport.Summary.Pass = 0
}
break
case "Fail":
if p.clusterReport.Summary.Fail--; p.clusterReport.Summary.Fail < 0 {
p.clusterReport.Summary.Fail = 0
}
break
default:
if p.clusterReport.Summary.Skip--; p.clusterReport.Summary.Skip < 0 {
p.clusterReport.Summary.Skip = 0
}
break
}
} else {
switch status {
case "Pass":
if p.report.Summary.Pass--; p.report.Summary.Pass < 0 {
p.report.Summary.Pass = 0
}
break
case "Fail":
if p.report.Summary.Fail--; p.report.Summary.Fail < 0 {
p.report.Summary.Fail = 0
}
break
default:
if p.report.Summary.Skip--; p.report.Summary.Skip < 0 {
p.report.Summary.Skip = 0
}
break
}
}
}
func (p *PolicyReport) IncreaseCount(status string, scope string) {
if scope == "CLUSTER" {
switch status {
case "Pass":
p.clusterReport.Summary.Pass++
break
case "Fail":
p.clusterReport.Summary.Fail++
break
default:
p.clusterReport.Summary.Skip++
break
}
} else {
switch status {
case "Pass":
p.report.Summary.Pass++
break
case "Fail":
p.report.Summary.Fail++
break
default:
p.report.Summary.Skip++
break
}
}
}