From c6398a0d3f99869c589dd00d4685be4abbb283b2 Mon Sep 17 00:00:00 2001 From: Binbin Li Date: Thu, 21 Sep 2023 06:23:36 +0000 Subject: [PATCH] feat: bump up Policy CRD to v1beta1 --- Makefile | 2 +- api/unversioned/policy_types.go | 12 +- api/v1alpha1/policy_conversion.go | 54 +++++++ api/v1alpha1/policy_types.go | 5 +- api/v1alpha1/zz_generated.conversion.go | 80 +++++----- api/v1beta1/policy_types.go | 80 ++++++++++ api/v1beta1/zz_generated.conversion.go | 140 ++++++++++++++++++ api/v1beta1/zz_generated.deepcopy.go | 90 +++++++++++ .../crds/policy-customresourcedefinition.yaml | 62 +++++++- .../config.ratify.deislabs.io_policies.yaml | 59 +++++++- .../policy/config_v1alpha1_policy_json.yaml | 3 +- .../policy/config_v1alpha1_policy_rego.yaml | 3 +- .../policy/config_v1beta1_policy_json.yaml | 9 ++ .../policy/config_v1beta1_policy_rego.yaml | 31 ++++ docs/reference/providers.md | 2 +- pkg/controllers/policy_controller.go | 40 ++++- pkg/controllers/policy_controller_test.go | 88 ++++++++++- pkg/policyprovider/factory/factory.go | 4 +- 18 files changed, 695 insertions(+), 69 deletions(-) create mode 100644 api/v1alpha1/policy_conversion.go create mode 100644 api/v1beta1/policy_types.go create mode 100644 config/samples/policy/config_v1beta1_policy_json.yaml create mode 100644 config/samples/policy/config_v1beta1_policy_rego.yaml diff --git a/Makefile b/Makefile index fac7c2a06..c0683b62b 100644 --- a/Makefile +++ b/Makefile @@ -118,7 +118,7 @@ delete-demo-constraints: .PHONY: deploy-rego-policy deploy-rego-policy: - kubectl apply -f ./config/samples/policy/config_v1alpha1_policy_rego.yaml + kubectl apply -f ./config/samples/policy/config_v1beta1_policy_rego.yaml .PHONY: deploy-gatekeeper deploy-gatekeeper: diff --git a/api/unversioned/policy_types.go b/api/unversioned/policy_types.go index f61246a63..1aaead7c5 100644 --- a/api/unversioned/policy_types.go +++ b/api/unversioned/policy_types.go @@ -25,7 +25,7 @@ import ( type PolicySpec struct { // Important: Run "make" to regenerate code after modifying this file - // Type of the polocy + // Type of the policy Type string `json:"type,omitempty"` // Parameters for this policy @@ -36,6 +36,16 @@ type PolicySpec struct { type PolicyStatus struct { // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster // Important: Run "make" to regenerate code after modifying this file + + // Is successful while applying the policy. + IsSuccess bool `json:"issuccess"` + + // Error message if policy is not successfully applied. + // +optional + Error string `json:"error,omitempty"` + // Truncated error message if the message is too long + // +optional + BriefError string `json:"brieferror,omitempty"` } // Policy is the Schema for the policies API diff --git a/api/v1alpha1/policy_conversion.go b/api/v1alpha1/policy_conversion.go new file mode 100644 index 000000000..7aeb061a9 --- /dev/null +++ b/api/v1alpha1/policy_conversion.go @@ -0,0 +1,54 @@ +/* +Copyright The Ratify 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 v1alpha1 + +import ( + unversioned "github.com/deislabs/ratify/api/unversioned" + conversion "k8s.io/apimachinery/pkg/conversion" +) + +//nolint:revive // ignore linter for autogenerated code +func Convert_unversioned_PolicySpec_To_v1alpha1_PolicySpec(in *unversioned.PolicySpec, out *PolicySpec, _ conversion.Scope) error { + out.Parameters = in.Parameters + return nil +} + +//nolint:revive // ignore linter for autogenerated code +func Convert_unversioned_PolicyStatus_To_v1alpha1_PolicyStatus(in *unversioned.PolicyStatus, out *PolicyStatus, _ conversion.Scope) error { + return nil +} + +//nolint:revive // ignore linter for autogenerated code +func Convert_unversioned_Policy_To_v1alpha1_Policy(in *unversioned.Policy, out *Policy, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + out.ObjectMeta.Name = in.Spec.Type + if err := Convert_unversioned_PolicySpec_To_v1alpha1_PolicySpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + return Convert_unversioned_PolicyStatus_To_v1alpha1_PolicyStatus(&in.Status, &out.Status, s) +} + +//nolint:revive // ignore linter for autogenerated code +func Convert_v1alpha1_Policy_To_unversioned_Policy(in *Policy, out *unversioned.Policy, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + out.ObjectMeta.Name = "ratify-policy" + if err := Convert_v1alpha1_PolicySpec_To_unversioned_PolicySpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + out.Spec.Type = in.ObjectMeta.Name + return Convert_v1alpha1_PolicyStatus_To_unversioned_PolicyStatus(&in.Status, &out.Status, s) +} diff --git a/api/v1alpha1/policy_types.go b/api/v1alpha1/policy_types.go index 43faed955..a1abeee51 100644 --- a/api/v1alpha1/policy_types.go +++ b/api/v1alpha1/policy_types.go @@ -28,9 +28,6 @@ import ( type PolicySpec struct { // Important: Run "make" to regenerate code after modifying this file - // Type of the polocy - Type string `json:"type,omitempty"` - // +kubebuilder:pruning:PreserveUnknownFields // Parameters for this policy Parameters runtime.RawExtension `json:"parameters,omitempty"` @@ -44,6 +41,7 @@ type PolicyStatus struct { // +kubebuilder:object:root=true // +kubebuilder:resource:scope="Cluster" +// +kubebuilder:deprecatedversion:warning="v1alpha1 of the Policy API has been deprecated. Please migrate to v1beta1." // Policy is the Schema for the policies API type Policy struct { metav1.TypeMeta `json:",inline"` @@ -54,7 +52,6 @@ type Policy struct { } // +kubebuilder:object:root=true -// +kubebuilder:storageversion // PolicyList contains a list of Policy type PolicyList struct { metav1.TypeMeta `json:",inline"` diff --git a/api/v1alpha1/zz_generated.conversion.go b/api/v1alpha1/zz_generated.conversion.go index dd2ac0e4a..2e6fd0418 100644 --- a/api/v1alpha1/zz_generated.conversion.go +++ b/api/v1alpha1/zz_generated.conversion.go @@ -85,11 +85,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*unversioned.Policy)(nil), (*Policy)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_unversioned_Policy_To_v1alpha1_Policy(a.(*unversioned.Policy), b.(*Policy), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*PolicyList)(nil), (*unversioned.PolicyList)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha1_PolicyList_To_unversioned_PolicyList(a.(*PolicyList), b.(*unversioned.PolicyList), scope) }); err != nil { @@ -105,21 +100,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*unversioned.PolicySpec)(nil), (*PolicySpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_unversioned_PolicySpec_To_v1alpha1_PolicySpec(a.(*unversioned.PolicySpec), b.(*PolicySpec), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*PolicyStatus)(nil), (*unversioned.PolicyStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha1_PolicyStatus_To_unversioned_PolicyStatus(a.(*PolicyStatus), b.(*unversioned.PolicyStatus), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*unversioned.PolicyStatus)(nil), (*PolicyStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_unversioned_PolicyStatus_To_v1alpha1_PolicyStatus(a.(*unversioned.PolicyStatus), b.(*PolicyStatus), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*Store)(nil), (*unversioned.Store)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha1_Store_To_unversioned_Store(a.(*Store), b.(*unversioned.Store), scope) }); err != nil { @@ -205,6 +190,21 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*unversioned.PolicySpec)(nil), (*PolicySpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_unversioned_PolicySpec_To_v1alpha1_PolicySpec(a.(*unversioned.PolicySpec), b.(*PolicySpec), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*unversioned.PolicyStatus)(nil), (*PolicyStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_unversioned_PolicyStatus_To_v1alpha1_PolicyStatus(a.(*unversioned.PolicyStatus), b.(*PolicyStatus), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*unversioned.Policy)(nil), (*Policy)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_unversioned_Policy_To_v1alpha1_Policy(a.(*unversioned.Policy), b.(*Policy), scope) + }); err != nil { + return err + } return nil } @@ -355,11 +355,6 @@ func autoConvert_v1alpha1_Policy_To_unversioned_Policy(in *Policy, out *unversio return nil } -// Convert_v1alpha1_Policy_To_unversioned_Policy is an autogenerated conversion function. -func Convert_v1alpha1_Policy_To_unversioned_Policy(in *Policy, out *unversioned.Policy, s conversion.Scope) error { - return autoConvert_v1alpha1_Policy_To_unversioned_Policy(in, out, s) -} - func autoConvert_unversioned_Policy_To_v1alpha1_Policy(in *unversioned.Policy, out *Policy, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta if err := Convert_unversioned_PolicySpec_To_v1alpha1_PolicySpec(&in.Spec, &out.Spec, s); err != nil { @@ -371,14 +366,19 @@ func autoConvert_unversioned_Policy_To_v1alpha1_Policy(in *unversioned.Policy, o return nil } -// Convert_unversioned_Policy_To_v1alpha1_Policy is an autogenerated conversion function. -func Convert_unversioned_Policy_To_v1alpha1_Policy(in *unversioned.Policy, out *Policy, s conversion.Scope) error { - return autoConvert_unversioned_Policy_To_v1alpha1_Policy(in, out, s) -} - func autoConvert_v1alpha1_PolicyList_To_unversioned_PolicyList(in *PolicyList, out *unversioned.PolicyList, s conversion.Scope) error { out.ListMeta = in.ListMeta - out.Items = *(*[]unversioned.Policy)(unsafe.Pointer(&in.Items)) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]unversioned.Policy, len(*in)) + for i := range *in { + if err := Convert_v1alpha1_Policy_To_unversioned_Policy(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } return nil } @@ -389,7 +389,17 @@ func Convert_v1alpha1_PolicyList_To_unversioned_PolicyList(in *PolicyList, out * func autoConvert_unversioned_PolicyList_To_v1alpha1_PolicyList(in *unversioned.PolicyList, out *PolicyList, s conversion.Scope) error { out.ListMeta = in.ListMeta - out.Items = *(*[]Policy)(unsafe.Pointer(&in.Items)) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Policy, len(*in)) + for i := range *in { + if err := Convert_unversioned_Policy_To_v1alpha1_Policy(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } return nil } @@ -399,7 +409,6 @@ func Convert_unversioned_PolicyList_To_v1alpha1_PolicyList(in *unversioned.Polic } func autoConvert_v1alpha1_PolicySpec_To_unversioned_PolicySpec(in *PolicySpec, out *unversioned.PolicySpec, s conversion.Scope) error { - out.Type = in.Type out.Parameters = in.Parameters return nil } @@ -410,16 +419,11 @@ func Convert_v1alpha1_PolicySpec_To_unversioned_PolicySpec(in *PolicySpec, out * } func autoConvert_unversioned_PolicySpec_To_v1alpha1_PolicySpec(in *unversioned.PolicySpec, out *PolicySpec, s conversion.Scope) error { - out.Type = in.Type + // WARNING: in.Type requires manual conversion: does not exist in peer-type out.Parameters = in.Parameters return nil } -// Convert_unversioned_PolicySpec_To_v1alpha1_PolicySpec is an autogenerated conversion function. -func Convert_unversioned_PolicySpec_To_v1alpha1_PolicySpec(in *unversioned.PolicySpec, out *PolicySpec, s conversion.Scope) error { - return autoConvert_unversioned_PolicySpec_To_v1alpha1_PolicySpec(in, out, s) -} - func autoConvert_v1alpha1_PolicyStatus_To_unversioned_PolicyStatus(in *PolicyStatus, out *unversioned.PolicyStatus, s conversion.Scope) error { return nil } @@ -430,14 +434,12 @@ func Convert_v1alpha1_PolicyStatus_To_unversioned_PolicyStatus(in *PolicyStatus, } func autoConvert_unversioned_PolicyStatus_To_v1alpha1_PolicyStatus(in *unversioned.PolicyStatus, out *PolicyStatus, s conversion.Scope) error { + // WARNING: in.IsSuccess requires manual conversion: does not exist in peer-type + // WARNING: in.Error requires manual conversion: does not exist in peer-type + // WARNING: in.BriefError requires manual conversion: does not exist in peer-type return nil } -// Convert_unversioned_PolicyStatus_To_v1alpha1_PolicyStatus is an autogenerated conversion function. -func Convert_unversioned_PolicyStatus_To_v1alpha1_PolicyStatus(in *unversioned.PolicyStatus, out *PolicyStatus, s conversion.Scope) error { - return autoConvert_unversioned_PolicyStatus_To_v1alpha1_PolicyStatus(in, out, s) -} - func autoConvert_v1alpha1_Store_To_unversioned_Store(in *Store, out *unversioned.Store, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta if err := Convert_v1alpha1_StoreSpec_To_unversioned_StoreSpec(&in.Spec, &out.Spec, s); err != nil { diff --git a/api/v1beta1/policy_types.go b/api/v1beta1/policy_types.go new file mode 100644 index 000000000..48909f454 --- /dev/null +++ b/api/v1beta1/policy_types.go @@ -0,0 +1,80 @@ +/* +Copyright The Ratify 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 v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// PolicySpec defines the desired state of Policy +type PolicySpec struct { + // Important: Run "make" to regenerate code after modifying this file + + // Type of the policy + Type string `json:"type,omitempty"` + + // +kubebuilder:pruning:PreserveUnknownFields + // Parameters for this policy + Parameters runtime.RawExtension `json:"parameters,omitempty"` +} + +// PolicyStatus defines the observed state of Policy +type PolicyStatus struct { + // Important: Run "make" to regenerate code after modifying this file + + // Is successful while applying the policy. + IsSuccess bool `json:"issuccess"` + + // Error message if policy is not successfully applied. + // +optional + Error string `json:"error,omitempty"` + // Truncated error message if the message is too long + // +optional + BriefError string `json:"brieferror,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:resource:scope="Cluster" +// +kubebuilder:subresource:status +// +kubebuilder:storageversion +// +kubebuilder:printcolumn:name="IsSuccess",type=boolean,JSONPath=`.status.issuccess` +// +kubebuilder:printcolumn:name="Error",type=string,JSONPath=`.status.brieferror` +// Policy is the Schema for the policies API +type Policy struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec PolicySpec `json:"spec,omitempty"` + Status PolicyStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:storageversion +// PolicyList contains a list of Policy +type PolicyList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Policy `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Policy{}, &PolicyList{}) +} diff --git a/api/v1beta1/zz_generated.conversion.go b/api/v1beta1/zz_generated.conversion.go index 246f18056..fbaa094f1 100644 --- a/api/v1beta1/zz_generated.conversion.go +++ b/api/v1beta1/zz_generated.conversion.go @@ -86,6 +86,46 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddGeneratedConversionFunc((*Policy)(nil), (*unversioned.Policy)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_Policy_To_unversioned_Policy(a.(*Policy), b.(*unversioned.Policy), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*unversioned.Policy)(nil), (*Policy)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_unversioned_Policy_To_v1beta1_Policy(a.(*unversioned.Policy), b.(*Policy), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*PolicyList)(nil), (*unversioned.PolicyList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_PolicyList_To_unversioned_PolicyList(a.(*PolicyList), b.(*unversioned.PolicyList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*unversioned.PolicyList)(nil), (*PolicyList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_unversioned_PolicyList_To_v1beta1_PolicyList(a.(*unversioned.PolicyList), b.(*PolicyList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*PolicySpec)(nil), (*unversioned.PolicySpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_PolicySpec_To_unversioned_PolicySpec(a.(*PolicySpec), b.(*unversioned.PolicySpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*unversioned.PolicySpec)(nil), (*PolicySpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_unversioned_PolicySpec_To_v1beta1_PolicySpec(a.(*unversioned.PolicySpec), b.(*PolicySpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*PolicyStatus)(nil), (*unversioned.PolicyStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_PolicyStatus_To_unversioned_PolicyStatus(a.(*PolicyStatus), b.(*unversioned.PolicyStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*unversioned.PolicyStatus)(nil), (*PolicyStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_unversioned_PolicyStatus_To_v1beta1_PolicyStatus(a.(*unversioned.PolicyStatus), b.(*PolicyStatus), scope) + }); err != nil { + return err + } if err := s.AddGeneratedConversionFunc((*Store)(nil), (*unversioned.Store)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta1_Store_To_unversioned_Store(a.(*Store), b.(*unversioned.Store), scope) }); err != nil { @@ -295,6 +335,106 @@ func Convert_unversioned_PluginSource_To_v1beta1_PluginSource(in *unversioned.Pl return autoConvert_unversioned_PluginSource_To_v1beta1_PluginSource(in, out, s) } +func autoConvert_v1beta1_Policy_To_unversioned_Policy(in *Policy, out *unversioned.Policy, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1beta1_PolicySpec_To_unversioned_PolicySpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1beta1_PolicyStatus_To_unversioned_PolicyStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_Policy_To_unversioned_Policy is an autogenerated conversion function. +func Convert_v1beta1_Policy_To_unversioned_Policy(in *Policy, out *unversioned.Policy, s conversion.Scope) error { + return autoConvert_v1beta1_Policy_To_unversioned_Policy(in, out, s) +} + +func autoConvert_unversioned_Policy_To_v1beta1_Policy(in *unversioned.Policy, out *Policy, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_unversioned_PolicySpec_To_v1beta1_PolicySpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_unversioned_PolicyStatus_To_v1beta1_PolicyStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_unversioned_Policy_To_v1beta1_Policy is an autogenerated conversion function. +func Convert_unversioned_Policy_To_v1beta1_Policy(in *unversioned.Policy, out *Policy, s conversion.Scope) error { + return autoConvert_unversioned_Policy_To_v1beta1_Policy(in, out, s) +} + +func autoConvert_v1beta1_PolicyList_To_unversioned_PolicyList(in *PolicyList, out *unversioned.PolicyList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]unversioned.Policy)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1beta1_PolicyList_To_unversioned_PolicyList is an autogenerated conversion function. +func Convert_v1beta1_PolicyList_To_unversioned_PolicyList(in *PolicyList, out *unversioned.PolicyList, s conversion.Scope) error { + return autoConvert_v1beta1_PolicyList_To_unversioned_PolicyList(in, out, s) +} + +func autoConvert_unversioned_PolicyList_To_v1beta1_PolicyList(in *unversioned.PolicyList, out *PolicyList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]Policy)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_unversioned_PolicyList_To_v1beta1_PolicyList is an autogenerated conversion function. +func Convert_unversioned_PolicyList_To_v1beta1_PolicyList(in *unversioned.PolicyList, out *PolicyList, s conversion.Scope) error { + return autoConvert_unversioned_PolicyList_To_v1beta1_PolicyList(in, out, s) +} + +func autoConvert_v1beta1_PolicySpec_To_unversioned_PolicySpec(in *PolicySpec, out *unversioned.PolicySpec, s conversion.Scope) error { + out.Type = in.Type + out.Parameters = in.Parameters + return nil +} + +// Convert_v1beta1_PolicySpec_To_unversioned_PolicySpec is an autogenerated conversion function. +func Convert_v1beta1_PolicySpec_To_unversioned_PolicySpec(in *PolicySpec, out *unversioned.PolicySpec, s conversion.Scope) error { + return autoConvert_v1beta1_PolicySpec_To_unversioned_PolicySpec(in, out, s) +} + +func autoConvert_unversioned_PolicySpec_To_v1beta1_PolicySpec(in *unversioned.PolicySpec, out *PolicySpec, s conversion.Scope) error { + out.Type = in.Type + out.Parameters = in.Parameters + return nil +} + +// Convert_unversioned_PolicySpec_To_v1beta1_PolicySpec is an autogenerated conversion function. +func Convert_unversioned_PolicySpec_To_v1beta1_PolicySpec(in *unversioned.PolicySpec, out *PolicySpec, s conversion.Scope) error { + return autoConvert_unversioned_PolicySpec_To_v1beta1_PolicySpec(in, out, s) +} + +func autoConvert_v1beta1_PolicyStatus_To_unversioned_PolicyStatus(in *PolicyStatus, out *unversioned.PolicyStatus, s conversion.Scope) error { + out.IsSuccess = in.IsSuccess + out.Error = in.Error + out.BriefError = in.BriefError + return nil +} + +// Convert_v1beta1_PolicyStatus_To_unversioned_PolicyStatus is an autogenerated conversion function. +func Convert_v1beta1_PolicyStatus_To_unversioned_PolicyStatus(in *PolicyStatus, out *unversioned.PolicyStatus, s conversion.Scope) error { + return autoConvert_v1beta1_PolicyStatus_To_unversioned_PolicyStatus(in, out, s) +} + +func autoConvert_unversioned_PolicyStatus_To_v1beta1_PolicyStatus(in *unversioned.PolicyStatus, out *PolicyStatus, s conversion.Scope) error { + out.IsSuccess = in.IsSuccess + out.Error = in.Error + out.BriefError = in.BriefError + return nil +} + +// Convert_unversioned_PolicyStatus_To_v1beta1_PolicyStatus is an autogenerated conversion function. +func Convert_unversioned_PolicyStatus_To_v1beta1_PolicyStatus(in *unversioned.PolicyStatus, out *PolicyStatus, s conversion.Scope) error { + return autoConvert_unversioned_PolicyStatus_To_v1beta1_PolicyStatus(in, out, s) +} + func autoConvert_v1beta1_Store_To_unversioned_Store(in *Store, out *unversioned.Store, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta if err := Convert_v1beta1_StoreSpec_To_unversioned_StoreSpec(&in.Spec, &out.Spec, s); err != nil { diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index b55ceca87..cb22292ee 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -136,6 +136,96 @@ func (in *PluginSource) DeepCopy() *PluginSource { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Policy) DeepCopyInto(out *Policy) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Policy. +func (in *Policy) DeepCopy() *Policy { + if in == nil { + return nil + } + out := new(Policy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Policy) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PolicyList) DeepCopyInto(out *PolicyList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Policy, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyList. +func (in *PolicyList) DeepCopy() *PolicyList { + if in == nil { + return nil + } + out := new(PolicyList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *PolicyList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PolicySpec) DeepCopyInto(out *PolicySpec) { + *out = *in + in.Parameters.DeepCopyInto(&out.Parameters) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicySpec. +func (in *PolicySpec) DeepCopy() *PolicySpec { + if in == nil { + return nil + } + out := new(PolicySpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PolicyStatus) DeepCopyInto(out *PolicyStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyStatus. +func (in *PolicyStatus) DeepCopy() *PolicyStatus { + if in == nil { + return nil + } + out := new(PolicyStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Store) DeepCopyInto(out *Store) { *out = *in diff --git a/charts/ratify/crds/policy-customresourcedefinition.yaml b/charts/ratify/crds/policy-customresourcedefinition.yaml index 4ccb69da7..40f71392c 100644 --- a/charts/ratify/crds/policy-customresourcedefinition.yaml +++ b/charts/ratify/crds/policy-customresourcedefinition.yaml @@ -15,7 +15,51 @@ spec: singular: policy scope: Cluster versions: - - name: v1alpha1 + - deprecated: true + deprecationWarning: + v1alpha1 of the Policy API has been deprecated. Please migrate + to v1beta1. + name: v1alpha1 + schema: + openAPIV3Schema: + description: Policy is the Schema for the policies API + properties: + apiVersion: + description: + "APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources" + type: string + kind: + description: + "Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds" + type: string + metadata: + type: object + spec: + description: PolicySpec defines the desired state of Policy + properties: + parameters: + description: Parameters for this policy + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + status: + description: PolicyStatus defines the observed state of Policy + type: object + type: object + served: true + storage: false + - additionalPrinterColumns: + - jsonPath: .status.issuccess + name: IsSuccess + type: boolean + - jsonPath: .status.brieferror + name: Error + type: string + name: v1beta1 schema: openAPIV3Schema: description: Policy is the Schema for the policies API @@ -42,12 +86,26 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true type: - description: Type of the polocy + description: Type of the policy type: string type: object status: description: PolicyStatus defines the observed state of Policy + properties: + brieferror: + description: Truncated error message if the message is too long + type: string + error: + description: Error message if policy is not successfully applied. + type: string + issuccess: + description: Is successful while applying the policy. + type: boolean + required: + - issuccess type: object type: object served: true storage: true + subresources: + status: {} diff --git a/config/crd/bases/config.ratify.deislabs.io_policies.yaml b/config/crd/bases/config.ratify.deislabs.io_policies.yaml index d4957133d..63f999782 100644 --- a/config/crd/bases/config.ratify.deislabs.io_policies.yaml +++ b/config/crd/bases/config.ratify.deislabs.io_policies.yaml @@ -15,7 +15,48 @@ spec: singular: policy scope: Cluster versions: - - name: v1alpha1 + - deprecated: true + deprecationWarning: v1alpha1 of the Policy API has been deprecated. Please migrate + to v1beta1. + name: v1alpha1 + schema: + openAPIV3Schema: + description: Policy is the Schema for the policies API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: PolicySpec defines the desired state of Policy + properties: + parameters: + description: Parameters for this policy + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + status: + description: PolicyStatus defines the observed state of Policy + type: object + type: object + served: true + storage: false + - additionalPrinterColumns: + - jsonPath: .status.issuccess + name: IsSuccess + type: boolean + - jsonPath: .status.brieferror + name: Error + type: string + name: v1beta1 schema: openAPIV3Schema: description: Policy is the Schema for the policies API @@ -40,12 +81,26 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true type: - description: Type of the polocy + description: Type of the policy type: string type: object status: description: PolicyStatus defines the observed state of Policy + properties: + brieferror: + description: Truncated error message if the message is too long + type: string + error: + description: Error message if policy is not successfully applied. + type: string + issuccess: + description: Is successful while applying the policy. + type: boolean + required: + - issuccess type: object type: object served: true storage: true + subresources: + status: {} diff --git a/config/samples/policy/config_v1alpha1_policy_json.yaml b/config/samples/policy/config_v1alpha1_policy_json.yaml index 2ba5743ff..127bab714 100644 --- a/config/samples/policy/config_v1alpha1_policy_json.yaml +++ b/config/samples/policy/config_v1alpha1_policy_json.yaml @@ -1,9 +1,8 @@ apiVersion: config.ratify.deislabs.io/v1alpha1 kind: Policy metadata: - name: "ratify-policy" + name: "configpolicy" spec: - type: "configpolicy" parameters: artifactVerificationPolicies: default: "all" diff --git a/config/samples/policy/config_v1alpha1_policy_rego.yaml b/config/samples/policy/config_v1alpha1_policy_rego.yaml index 8a5d8577c..f80978309 100644 --- a/config/samples/policy/config_v1alpha1_policy_rego.yaml +++ b/config/samples/policy/config_v1alpha1_policy_rego.yaml @@ -1,9 +1,8 @@ apiVersion: config.ratify.deislabs.io/v1alpha1 kind: Policy metadata: - name: "ratify-policy" + name: "regopolicy" spec: - type: "regopolicy" parameters: passthroughEnabled: false policy: | diff --git a/config/samples/policy/config_v1beta1_policy_json.yaml b/config/samples/policy/config_v1beta1_policy_json.yaml new file mode 100644 index 000000000..1fbf1adba --- /dev/null +++ b/config/samples/policy/config_v1beta1_policy_json.yaml @@ -0,0 +1,9 @@ +apiVersion: config.ratify.deislabs.io/v1beta1 +kind: Policy +metadata: + name: "ratify-policy" +spec: + type: "config-policy" + parameters: + artifactVerificationPolicies: + default: "all" diff --git a/config/samples/policy/config_v1beta1_policy_rego.yaml b/config/samples/policy/config_v1beta1_policy_rego.yaml new file mode 100644 index 000000000..89ac6a056 --- /dev/null +++ b/config/samples/policy/config_v1beta1_policy_rego.yaml @@ -0,0 +1,31 @@ +apiVersion: config.ratify.deislabs.io/v1beta1 +kind: Policy +metadata: + name: "ratify-policy" +spec: + type: "rego-policy" + parameters: + passthroughEnabled: false + policy: | + package ratify.policy + + default valid := false + + # all artifacts MUST be valid + valid { + not failed_verify(input) + } + + # all reports MUST pass the verification + failed_verify(reports) { + [path, value] := walk(reports) + value == false + path[count(path) - 1] == "isSuccess" + } + + # each artifact MUST have at least one report + failed_verify(reports) { + [path, value] := walk(reports) + path[count(path) - 1] == "verifierReports" + count(value) == 0 + } diff --git a/docs/reference/providers.md b/docs/reference/providers.md index b3ca3bbf2..72aa88f74 100644 --- a/docs/reference/providers.md +++ b/docs/reference/providers.md @@ -42,7 +42,7 @@ Ratify embeds OPA engine inside the executor to provide a built-in policy provid 1. Set the helm chart value of `policy.useRego` to `true` while deploying Ratify. 2. Apply a Policy Custom Resource with Rego Policy if the service is up. e.g. ```bash -kubectl apply -f ./config/samples/policy/config_v1alpha1_policy_rego.yaml +kubectl apply -f ./config/samples/policy/config_v1beta1_policy_rego.yaml ``` And if Ratify is used as command line tool, users MUST provide a config with Rego Policy. Check `test/bats/tests/config/config_rego_policy_notation_leaf_cert.json` as an example. diff --git a/pkg/controllers/policy_controller.go b/pkg/controllers/policy_controller.go index 0a8af2cb7..2fe678445 100644 --- a/pkg/controllers/policy_controller.go +++ b/pkg/controllers/policy_controller.go @@ -20,7 +20,7 @@ import ( "encoding/json" "fmt" - configv1alpha1 "github.com/deislabs/ratify/api/v1alpha1" + configv1beta1 "github.com/deislabs/ratify/api/v1beta1" "github.com/deislabs/ratify/pkg/policyprovider" "github.com/deislabs/ratify/pkg/policyprovider/config" pf "github.com/deislabs/ratify/pkg/policyprovider/factory" @@ -62,7 +62,7 @@ var ActivePolicy policy func (r *PolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { policyLogger := logrus.WithContext(ctx) - var policy configv1alpha1.Policy + var policy configv1beta1.Policy var resource = req.Name policyLogger.Infof("Reconciling Policy %s", resource) @@ -77,11 +77,15 @@ func (r *PolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr } if resource != ratifyPolicy { + errStr := fmt.Sprintf("metadata.name must be ratify-policy, got %s", resource) + policyLogger.Error(errStr) + writePolicyStatus(ctx, r, &policy, policyLogger, false, errStr) return ctrl.Result{}, nil } if err := policyAddOrReplace(policy.Spec); err != nil { policyLogger.Error("unable to create policy from policy crd: ", err) + writePolicyStatus(ctx, r, &policy, policyLogger, false, err.Error()) return ctrl.Result{}, err } @@ -91,11 +95,11 @@ func (r *PolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr // SetupWithManager sets up the controller with the Manager. func (r *PolicyReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). - For(&configv1alpha1.Policy{}). + For(&configv1beta1.Policy{}). Complete(r) } -func policyAddOrReplace(spec configv1alpha1.PolicySpec) error { +func policyAddOrReplace(spec configv1beta1.PolicySpec) error { policyEnforcer, err := specToPolicyEnforcer(spec) if err != nil { return fmt.Errorf("failed to create policy enforcer: %w", err) @@ -106,7 +110,7 @@ func policyAddOrReplace(spec configv1alpha1.PolicySpec) error { return nil } -func specToPolicyEnforcer(spec configv1alpha1.PolicySpec) (policyprovider.PolicyProvider, error) { +func specToPolicyEnforcer(spec configv1beta1.PolicySpec) (policyprovider.PolicyProvider, error) { policyConfig, err := rawToPolicyConfig(spec.Parameters.Raw, spec.Type) if err != nil { return nil, fmt.Errorf("failed to parse policy config: %w", err) @@ -148,3 +152,29 @@ func (p *policy) deletePolicy(resource string) { func (p *policy) IsEmpty() bool { return p.Name == "" && p.Enforcer == nil } + +func writePolicyStatus(ctx context.Context, r client.StatusClient, policy *configv1beta1.Policy, logger *logrus.Entry, isSuccess bool, errString string) { + if isSuccess { + updatePolicySuccessStatus(policy) + } else { + updatePolicyErrorStatus(policy, errString) + } + if statusErr := r.Status().Update(ctx, policy); statusErr != nil { + logger.Error(statusErr, ", unbale to update policy error status") + } +} + +func updatePolicySuccessStatus(policy *configv1beta1.Policy) { + policy.Status.IsSuccess = true + policy.Status.Error = "" +} + +func updatePolicyErrorStatus(policy *configv1beta1.Policy, errString string) { + briefErr := errString + if len(errString) > maxBriefErrLength { + briefErr = fmt.Sprintf("%s...", errString[:maxBriefErrLength]) + } + policy.Status.IsSuccess = false + policy.Status.Error = errString + policy.Status.BriefError = briefErr +} diff --git a/pkg/controllers/policy_controller_test.go b/pkg/controllers/policy_controller_test.go index 130e9d7ae..d3b041719 100644 --- a/pkg/controllers/policy_controller_test.go +++ b/pkg/controllers/policy_controller_test.go @@ -16,13 +16,17 @@ limitations under the License. package controllers import ( + "context" + "errors" "reflect" "testing" - configv1alpha1 "github.com/deislabs/ratify/api/v1alpha1" + configv1beta1 "github.com/deislabs/ratify/api/v1beta1" "github.com/deislabs/ratify/pkg/policyprovider/config" _ "github.com/deislabs/ratify/pkg/policyprovider/configpolicy" + "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" ) const ( @@ -30,6 +34,35 @@ const ( policyName2 = "policy2" ) +type mockResourceWriter struct { + updateFailed bool +} + +func (w mockResourceWriter) Create(_ context.Context, _ client.Object, _ client.Object, _ ...client.SubResourceCreateOption) error { + return nil +} + +func (w mockResourceWriter) Update(_ context.Context, _ client.Object, _ ...client.SubResourceUpdateOption) error { + if w.updateFailed { + return errors.New("update failed") + } + return nil +} + +func (w mockResourceWriter) Patch(_ context.Context, _ client.Object, _ client.Patch, _ ...client.SubResourcePatchOption) error { + return nil +} + +type mockStatusClient struct { + updateFailed bool +} + +func (c mockStatusClient) Status() client.SubResourceWriter { + writer := mockResourceWriter{} + writer.updateFailed = c.updateFailed + return writer +} + func TestDeletePolicy(t *testing.T) { testCases := []struct { name string @@ -140,14 +173,14 @@ func TestSpecToPolicyEnforcer(t *testing.T) { testCases := []struct { name string policyName string - spec configv1alpha1.PolicySpec + spec configv1beta1.PolicySpec expectErr bool expectProvider bool }{ { name: "invalid spec", policyName: policyName1, - spec: configv1alpha1.PolicySpec{ + spec: configv1beta1.PolicySpec{ Type: policyName1, }, expectErr: true, @@ -155,7 +188,7 @@ func TestSpecToPolicyEnforcer(t *testing.T) { }, { name: "non-supported policy", - spec: configv1alpha1.PolicySpec{ + spec: configv1beta1.PolicySpec{ Parameters: runtime.RawExtension{ Raw: []byte("{\"name\": \"policy1\"}"), }, @@ -166,7 +199,7 @@ func TestSpecToPolicyEnforcer(t *testing.T) { }, { name: "valid spec", - spec: configv1alpha1.PolicySpec{ + spec: configv1beta1.PolicySpec{ Parameters: runtime.RawExtension{ Raw: []byte("{\"name\": \"configpolicy\"}"), }, @@ -194,20 +227,20 @@ func TestSpecToPolicyEnforcer(t *testing.T) { func TestPolicyAddOrReplace(t *testing.T) { testCases := []struct { name string - spec configv1alpha1.PolicySpec + spec configv1beta1.PolicySpec policyName string expectErr bool }{ { name: "invalid spec", - spec: configv1alpha1.PolicySpec{ + spec: configv1beta1.PolicySpec{ Type: policyName1, }, expectErr: true, }, { name: "valid spec", - spec: configv1alpha1.PolicySpec{ + spec: configv1beta1.PolicySpec{ Parameters: runtime.RawExtension{ Raw: []byte("{\"name\": \"configpolicy\"}"), }, @@ -227,3 +260,42 @@ func TestPolicyAddOrReplace(t *testing.T) { }) } } + +func TestWritePolicyStatus(t *testing.T) { + logger := logrus.WithContext(context.Background()) + testCases := []struct { + name string + isSuccess bool + policy *configv1beta1.Policy + errString string + reconciler client.StatusClient + }{ + { + name: "success status", + isSuccess: true, + policy: &configv1beta1.Policy{}, + reconciler: &mockStatusClient{}, + }, + { + name: "error status", + isSuccess: false, + policy: &configv1beta1.Policy{}, + errString: "a long error string that exceeds the max length of 30 characters", + reconciler: &mockStatusClient{}, + }, + { + name: "status update failed", + isSuccess: true, + policy: &configv1beta1.Policy{}, + reconciler: &mockStatusClient{ + updateFailed: true, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + writePolicyStatus(context.Background(), tc.reconciler, tc.policy, logger, tc.isSuccess, tc.errString) + }) + } +} diff --git a/pkg/policyprovider/factory/factory.go b/pkg/policyprovider/factory/factory.go index d43b18bf2..81b097543 100644 --- a/pkg/policyprovider/factory/factory.go +++ b/pkg/policyprovider/factory/factory.go @@ -57,11 +57,11 @@ func CreatePolicyProviderFromConfig(policyConfig config.PoliciesConfig) (policyp return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.PolicyProvider).WithDetail(fmt.Sprintf("failed to find policy provider name in the policy config with key: %s", types.Name)) } - providerNameStr := strings.ToLower(fmt.Sprintf("%s", policyProviderName)) + providerNameStr := strings.Replace(strings.ToLower(fmt.Sprintf("%s", policyProviderName)), "-", "", -1) policyFactory, ok := builtInPolicyProviders[providerNameStr] if !ok { - return nil, re.ErrorCodePolicyProviderNotFound.NewError(re.PolicyProvider, providerNameStr, re.EmptyLink, nil, "failed to find registered policy provider", re.HideStackTrace) + return nil, re.ErrorCodePolicyProviderNotFound.NewError(re.PolicyProvider, providerNameStr, re.EmptyLink, nil, fmt.Sprintf("policy type: %s is not registered policy provider", providerNameStr), re.HideStackTrace) } policyProvider, err := policyFactory.Create(policyConfig.PolicyPlugin)