2022-09-06 17:16:44 +02:00
package yaml
2020-09-01 09:11:20 -07:00
import (
"encoding/json"
"fmt"
2023-05-10 11:12:53 +03:00
"strings"
2020-09-01 09:11:20 -07:00
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
}
2022-11-11 16:18:17 +01:00
us := & unstructured . Unstructured { }
if err := json . Unmarshal ( policyBytes , us ) ; 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 ]
2024-01-23 13:47:38 +02:00
if policies , validatingAdmissionPolicies , validatingAdmissionPolicyBindings , err = addPolicy ( policies , validatingAdmissionPolicies , validatingAdmissionPolicyBindings , & item ) ; err != nil {
return nil , nil , nil , err
2022-11-11 16:18:17 +01:00
}
2021-10-01 14:16:33 +05:30
}
2022-09-06 17:16:44 +02:00
} else {
2024-01-23 13:47:38 +02:00
if policies , validatingAdmissionPolicies , validatingAdmissionPolicyBindings , err = addPolicy ( policies , validatingAdmissionPolicies , validatingAdmissionPolicyBindings , us ) ; err != nil {
return nil , nil , nil , err
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
}
2024-08-29 18:31:25 +03:00
func addPolicy ( policies [ ] kyvernov1 . PolicyInterface , validatingAdmissionPolicies [ ] admissionregistrationv1beta1 . ValidatingAdmissionPolicy , validatingAdmissionPolicyBindings [ ] admissionregistrationv1beta1 . ValidatingAdmissionPolicyBinding , us * unstructured . Unstructured ) ( [ ] kyvernov1 . PolicyInterface , [ ] admissionregistrationv1beta1 . ValidatingAdmissionPolicy , [ ] admissionregistrationv1beta1 . ValidatingAdmissionPolicyBinding , error ) {
2023-05-10 11:12:53 +03:00
kind := us . GetKind ( )
2022-11-11 16:18:17 +01:00
2023-05-10 11:12:53 +03:00
if strings . Compare ( kind , "ValidatingAdmissionPolicy" ) == 0 {
2024-08-29 18:31:25 +03:00
validatingAdmissionPolicy := admissionregistrationv1beta1 . ValidatingAdmissionPolicy { }
2022-11-11 16:18:17 +01:00
2023-09-14 02:30:23 +02:00
if err := runtime . DefaultUnstructuredConverter . FromUnstructuredWithValidation ( us . Object , & validatingAdmissionPolicy , true ) ; err != nil {
2024-01-23 13:47:38 +02:00
return policies , nil , validatingAdmissionPolicyBindings , fmt . Errorf ( "failed to decode policy: %v" , err )
2023-05-10 11:12:53 +03:00
}
2022-11-11 16:18:17 +01:00
2023-05-10 11:12:53 +03:00
if validatingAdmissionPolicy . Kind == "" {
log . V ( 3 ) . Info ( "skipping file as ValidatingAdmissionPolicy.Kind not found" )
2024-01-23 13:47:38 +02:00
return policies , validatingAdmissionPolicies , validatingAdmissionPolicyBindings , nil
2021-10-01 14:16:33 +05:30
}
2023-05-10 11:12:53 +03:00
2023-09-14 02:30:23 +02:00
validatingAdmissionPolicies = append ( validatingAdmissionPolicies , validatingAdmissionPolicy )
2024-01-23 13:47:38 +02:00
} else if strings . Compare ( kind , "ValidatingAdmissionPolicyBinding" ) == 0 {
2024-08-29 18:31:25 +03:00
validatingAdmissionPolicyBinding := admissionregistrationv1beta1 . ValidatingAdmissionPolicyBinding { }
2024-01-23 13:47:38 +02:00
if err := runtime . DefaultUnstructuredConverter . FromUnstructuredWithValidation ( us . Object , & validatingAdmissionPolicyBinding , true ) ; err != nil {
return policies , validatingAdmissionPolicies , nil , fmt . Errorf ( "failed to decode policy: %v" , err )
}
if validatingAdmissionPolicyBinding . Kind == "" {
log . V ( 3 ) . Info ( "skipping file as ValidatingAdmissionPolicyBinding.Kind not found" )
return policies , validatingAdmissionPolicies , validatingAdmissionPolicyBindings , nil
}
validatingAdmissionPolicyBindings = append ( validatingAdmissionPolicyBindings , validatingAdmissionPolicyBinding )
2022-11-11 16:18:17 +01:00
} else {
2023-05-10 11:12:53 +03:00
var policy kyvernov1 . PolicyInterface
if us . GetKind ( ) == "ClusterPolicy" {
policy = & kyvernov1 . ClusterPolicy { }
2023-09-14 18:54:54 +02:00
} else if us . GetKind ( ) == "Policy" {
2023-05-10 11:12:53 +03:00
policy = & kyvernov1 . Policy { }
2023-09-14 18:54:54 +02:00
} else {
2024-01-23 13:47:38 +02:00
return policies , validatingAdmissionPolicies , validatingAdmissionPolicyBindings , nil
2023-05-10 11:12:53 +03:00
}
2023-09-14 02:30:23 +02:00
if err := runtime . DefaultUnstructuredConverter . FromUnstructuredWithValidation ( us . Object , policy , true ) ; err != nil {
2024-01-23 13:47:38 +02:00
return nil , validatingAdmissionPolicies , validatingAdmissionPolicyBindings , fmt . Errorf ( "failed to decode policy: %v" , err )
2023-05-10 11:12:53 +03:00
}
if policy . GetKind ( ) == "" {
log . V ( 3 ) . Info ( "skipping file as policy.TypeMeta.Kind not found" )
2024-01-23 13:47:38 +02:00
return policies , validatingAdmissionPolicies , validatingAdmissionPolicyBindings , nil
2023-05-10 11:12:53 +03:00
}
if policy . GetKind ( ) != "ClusterPolicy" && policy . GetKind ( ) != "Policy" {
2024-01-23 13:47:38 +02:00
return nil , validatingAdmissionPolicies , validatingAdmissionPolicyBindings , fmt . Errorf ( "resource %s/%s is not a Policy or a ClusterPolicy" , policy . GetKind ( ) , policy . GetName ( ) )
2023-05-10 11:12:53 +03:00
}
if policy . GetKind ( ) == "Policy" {
if policy . GetNamespace ( ) == "" {
policy . SetNamespace ( "default" )
}
} else {
policy . SetNamespace ( "" )
}
policies = append ( policies , policy )
2020-09-01 09:11:20 -07:00
}
2023-05-10 11:12:53 +03:00
2024-01-23 13:47:38 +02:00
return policies , validatingAdmissionPolicies , validatingAdmissionPolicyBindings , nil
2020-09-01 09:11:20 -07:00
}