2022-09-06 17:16:44 +02:00
|
|
|
package yaml
|
2020-09-01 09:11:20 -07:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
2022-05-17 13:12:43 +02:00
|
|
|
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
2023-10-27 13:08:39 +02:00
|
|
|
extyaml "github.com/kyverno/kyverno/ext/yaml"
|
2022-10-02 20:45:03 +01:00
|
|
|
log "github.com/kyverno/kyverno/pkg/logging"
|
2024-08-29 18:31:25 +03:00
|
|
|
admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1"
|
2022-11-11 16:18:17 +01:00
|
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
|
|
"k8s.io/apimachinery/pkg/runtime"
|
2020-09-01 09:11:20 -07:00
|
|
|
"k8s.io/apimachinery/pkg/util/yaml"
|
|
|
|
)
|
|
|
|
|
2022-09-06 17:16:44 +02:00
|
|
|
// GetPolicy extracts policies from YAML bytes
|
2024-08-29 18:31:25 +03:00
|
|
|
func GetPolicy(bytes []byte) (policies []kyvernov1.PolicyInterface, validatingAdmissionPolicies []admissionregistrationv1beta1.ValidatingAdmissionPolicy, validatingAdmissionPolicyBindings []admissionregistrationv1beta1.ValidatingAdmissionPolicyBinding, err error) {
|
2023-10-27 13:08:39 +02:00
|
|
|
documents, err := extyaml.SplitDocuments(bytes)
|
2020-09-01 09:11:20 -07:00
|
|
|
if err != nil {
|
2024-01-23 13:47:38 +02:00
|
|
|
return nil, nil, nil, err
|
2020-09-01 09:11:20 -07:00
|
|
|
}
|
2022-04-01 11:56:16 +02:00
|
|
|
for _, thisPolicyBytes := range documents {
|
2020-09-01 09:11:20 -07:00
|
|
|
policyBytes, err := yaml.ToJSON(thisPolicyBytes)
|
|
|
|
if err != nil {
|
2024-01-23 13:47:38 +02:00
|
|
|
return nil, nil, nil, fmt.Errorf("failed to convert to JSON: %v", err)
|
2020-09-01 09:11:20 -07:00
|
|
|
}
|
2025-01-10 10:30:54 +01:00
|
|
|
var us unstructured.Unstructured
|
|
|
|
if err := us.UnmarshalJSON(policyBytes); err != nil {
|
2024-01-23 13:47:38 +02:00
|
|
|
return nil, nil, nil, fmt.Errorf("failed to decode policy: %v", err)
|
2020-09-01 09:11:20 -07:00
|
|
|
}
|
2022-11-11 16:18:17 +01:00
|
|
|
if us.IsList() {
|
|
|
|
list, err := us.ToList()
|
|
|
|
if err != nil {
|
2024-01-23 13:47:38 +02:00
|
|
|
return nil, nil, nil, fmt.Errorf("failed to decode policy list: %v", err)
|
2022-11-11 16:18:17 +01:00
|
|
|
}
|
|
|
|
for i := range list.Items {
|
|
|
|
item := list.Items[i]
|
2025-01-10 10:30:54 +01:00
|
|
|
vap, vapb, pol, err := parse(item)
|
|
|
|
if err != nil {
|
2024-01-23 13:47:38 +02:00
|
|
|
return nil, nil, nil, err
|
2022-11-11 16:18:17 +01:00
|
|
|
}
|
2025-01-10 10:30:54 +01:00
|
|
|
if vap != nil {
|
|
|
|
validatingAdmissionPolicies = append(validatingAdmissionPolicies, *vap)
|
|
|
|
}
|
|
|
|
if vapb != nil {
|
|
|
|
validatingAdmissionPolicyBindings = append(validatingAdmissionPolicyBindings, *vapb)
|
|
|
|
}
|
|
|
|
if pol != nil {
|
|
|
|
policies = append(policies, pol)
|
|
|
|
}
|
2021-10-01 14:16:33 +05:30
|
|
|
}
|
2022-09-06 17:16:44 +02:00
|
|
|
} else {
|
2025-01-10 10:30:54 +01:00
|
|
|
vap, vapb, pol, err := parse(us)
|
|
|
|
if err != nil {
|
2024-01-23 13:47:38 +02:00
|
|
|
return nil, nil, nil, err
|
2022-11-11 16:18:17 +01:00
|
|
|
}
|
2025-01-10 10:30:54 +01:00
|
|
|
if vap != nil {
|
|
|
|
validatingAdmissionPolicies = append(validatingAdmissionPolicies, *vap)
|
|
|
|
}
|
|
|
|
if vapb != nil {
|
|
|
|
validatingAdmissionPolicyBindings = append(validatingAdmissionPolicyBindings, *vapb)
|
|
|
|
}
|
|
|
|
if pol != nil {
|
|
|
|
policies = append(policies, pol)
|
|
|
|
}
|
2022-11-11 16:18:17 +01:00
|
|
|
}
|
|
|
|
}
|
2024-01-23 13:47:38 +02:00
|
|
|
return policies, validatingAdmissionPolicies, validatingAdmissionPolicyBindings, err
|
2022-11-11 16:18:17 +01:00
|
|
|
}
|
|
|
|
|
2025-01-10 10:30:54 +01:00
|
|
|
func parse(obj unstructured.Unstructured) (
|
|
|
|
*admissionregistrationv1beta1.ValidatingAdmissionPolicy,
|
|
|
|
*admissionregistrationv1beta1.ValidatingAdmissionPolicyBinding,
|
|
|
|
kyvernov1.PolicyInterface,
|
|
|
|
error,
|
|
|
|
) {
|
|
|
|
switch obj.GetKind() {
|
|
|
|
case "ValidatingAdmissionPolicy":
|
|
|
|
out, err := parseValidatingAdmissionPolicy(obj)
|
|
|
|
return out, nil, nil, err
|
|
|
|
case "ValidatingAdmissionPolicyBinding":
|
|
|
|
out, err := parseValidatingAdmissionPolicyBinding(obj)
|
|
|
|
return nil, out, nil, err
|
|
|
|
case "Policy":
|
|
|
|
out, err := parsePolicy(obj)
|
|
|
|
return nil, nil, out, err
|
|
|
|
case "ClusterPolicy":
|
|
|
|
out, err := parseClusterPolicy(obj)
|
|
|
|
return nil, nil, out, err
|
|
|
|
}
|
|
|
|
return nil, nil, nil, nil
|
|
|
|
}
|
2023-05-10 11:12:53 +03:00
|
|
|
|
2025-01-10 10:30:54 +01:00
|
|
|
func parseValidatingAdmissionPolicy(obj unstructured.Unstructured) (*admissionregistrationv1beta1.ValidatingAdmissionPolicy, error) {
|
|
|
|
var out admissionregistrationv1beta1.ValidatingAdmissionPolicy
|
|
|
|
if err := runtime.DefaultUnstructuredConverter.FromUnstructuredWithValidation(obj.Object, &out, true); err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to decode policy: %v", err)
|
|
|
|
}
|
|
|
|
if out.Kind == "" {
|
|
|
|
log.V(3).Info("skipping file as ValidatingAdmissionPolicy.Kind not found")
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
return &out, nil
|
|
|
|
}
|
2023-05-10 11:12:53 +03:00
|
|
|
|
2025-01-10 10:30:54 +01:00
|
|
|
func parseValidatingAdmissionPolicyBinding(obj unstructured.Unstructured) (*admissionregistrationv1beta1.ValidatingAdmissionPolicyBinding, error) {
|
|
|
|
var out admissionregistrationv1beta1.ValidatingAdmissionPolicyBinding
|
|
|
|
if err := runtime.DefaultUnstructuredConverter.FromUnstructuredWithValidation(obj.Object, &out, true); err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to decode policy: %v", err)
|
|
|
|
}
|
|
|
|
if out.Kind == "" {
|
|
|
|
log.V(3).Info("skipping file as ValidatingAdmissionPolicyBinding.Kind not found")
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
return &out, nil
|
|
|
|
}
|
2023-05-10 11:12:53 +03:00
|
|
|
|
2025-01-10 10:30:54 +01:00
|
|
|
func parsePolicy(obj unstructured.Unstructured) (*kyvernov1.Policy, error) {
|
|
|
|
var out kyvernov1.Policy
|
|
|
|
if err := runtime.DefaultUnstructuredConverter.FromUnstructuredWithValidation(obj.Object, &out, true); err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to decode policy: %v", err)
|
2020-09-01 09:11:20 -07:00
|
|
|
}
|
2025-01-10 10:30:54 +01:00
|
|
|
if out.Kind == "" {
|
|
|
|
log.V(3).Info("skipping file as Policy.Kind not found")
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
if out.GetNamespace() == "" {
|
|
|
|
out.SetNamespace("default")
|
|
|
|
}
|
|
|
|
return &out, nil
|
|
|
|
}
|
2023-05-10 11:12:53 +03:00
|
|
|
|
2025-01-10 10:30:54 +01:00
|
|
|
func parseClusterPolicy(obj unstructured.Unstructured) (*kyvernov1.ClusterPolicy, error) {
|
|
|
|
var out kyvernov1.ClusterPolicy
|
|
|
|
if err := runtime.DefaultUnstructuredConverter.FromUnstructuredWithValidation(obj.Object, &out, true); err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to decode policy: %v", err)
|
|
|
|
}
|
|
|
|
if out.Kind == "" {
|
|
|
|
log.V(3).Info("skipping file as ClusterPolicy.Kind not found")
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
out.SetNamespace("")
|
|
|
|
return &out, nil
|
2020-09-01 09:11:20 -07:00
|
|
|
}
|