Skip to content

Commit

Permalink
Merge pull request rancher#45149 from jiaqiluo/psact-enhancement
Browse files Browse the repository at this point in the history
  • Loading branch information
jiaqiluo authored Apr 29, 2024
2 parents 21ccf17 + 924ce56 commit 8298de0
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ func (c *checker) updateClusterConnectedCondition(cluster *v3.Cluster, connected
v3.ClusterConditionReady.Reason(cluster, "Disconnected")
v3.ClusterConditionReady.Message(cluster, "Cluster agent is not connected")
}
logrus.Tracef("[clusterConnectedCondition] update cluster %v", cluster.Name)
_, err := c.clusters.Update(cluster)
if apierror.IsConflict(err) {
cluster, err = c.clusters.Get(cluster.Name, metav1.GetOptions{})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ func (h *HealthSyncer) updateClusterHealth() error {
}

if !reflect.DeepEqual(oldCluster, newObj) {
logrus.Tracef("[healthSyncer] update cluster %s", cluster.Name)
if _, err := h.clusters.Update(newObj.(*v3.Cluster)); err != nil {
return errors.Wrapf(err, "[updateClusterHealth] Failed to update cluster [%s]", cluster.Name)
}
Expand Down
51 changes: 47 additions & 4 deletions pkg/data/management/podadmissionconfigurationtemplate_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import (

v3 "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3"
"github.com/rancher/rancher/pkg/types/config"
"github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/util/retry"
"k8s.io/gengo/examples/set-gen/sets"
)

var FeatureAppNS = []string{
Expand Down Expand Up @@ -34,20 +37,60 @@ var FeatureAppNS = []string{
"cattle-provisioning-capi-system", // CAPI core controller manager
}

// addDefaultPodSecurityAdmissionConfigurationTemplates creates or updates the default PSACTs with the builtin templates.
func addDefaultPodSecurityAdmissionConfigurationTemplates(management *config.ManagementContext) error {
psapts := management.Management.PodSecurityAdmissionConfigurationTemplates("")
psactClient := management.Management.PodSecurityAdmissionConfigurationTemplates("")
templates := []*v3.PodSecurityAdmissionConfigurationTemplate{
newPodSecurityAdmissionConfigurationTemplatePrivileged(),
newPodSecurityAdmissionConfigurationTemplateRestricted(),
}
for _, template := range templates {
if _, err := psapts.Create(template); err != nil && !errors.IsAlreadyExists(err) {
return fmt.Errorf("error creating default '%s' pod security admission configuration template: %w", template.Name, err)
for _, t := range templates {
if _, err := psactClient.Create(t); err != nil {
if !errors.IsAlreadyExists(err) {
return fmt.Errorf("failed to create default '%s' pod security admission configuration: %w", t.Name, err)
}
logrus.Tracef("updating default '%s' pod security admission configuration", t.Name)
err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
// get the latest version of the object from the k8s API directly
existing, err := psactClient.Get(t.Name, metav1.GetOptions{})
if err != nil {
return err
}
// We'd like to preserve user's additions to the exemptions, meanwhile merging everything from
// the built-in template into the existing psact for Rancher to work properly. It means that any
// value that is still in the built-in template but removed by user will be added back.
final := mergeExemptions(existing, t)
if _, err = psactClient.Update(final); err != nil {
return err
}
return nil
})
if err != nil {
return err
}
}
}
return nil
}

// mergeExemptions returns a new pointer to PodSecurityAdmissionConfigurationTemplate which values are copied from
// the base but the exemptions field is the union set of the values from the base and the additional PSACT.
func mergeExemptions(base, additional *v3.PodSecurityAdmissionConfigurationTemplate) *v3.PodSecurityAdmissionConfigurationTemplate {
if base == nil {
return additional
}
if additional == nil {
return base
}
a := base.Configuration.Exemptions
b := additional.Configuration.Exemptions
final := base.DeepCopy()
final.Configuration.Exemptions.Usernames = sets.NewString(a.Usernames...).Insert(b.Usernames...).List()
final.Configuration.Exemptions.Namespaces = sets.NewString(a.Namespaces...).Insert(b.Namespaces...).List()
final.Configuration.Exemptions.RuntimeClasses = sets.NewString(a.RuntimeClasses...).Insert(b.RuntimeClasses...).List()
return final
}

func newPodSecurityAdmissionConfigurationTemplateRestricted() *v3.PodSecurityAdmissionConfigurationTemplate {
return &v3.PodSecurityAdmissionConfigurationTemplate{
ObjectMeta: metav1.ObjectMeta{
Expand Down
117 changes: 117 additions & 0 deletions pkg/data/management/podadmissionconfigurationtemplate_data_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package management

import (
"testing"

v3 "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3"
"github.com/stretchr/testify/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var (
example1 = &v3.PodSecurityAdmissionConfigurationTemplate{
ObjectMeta: metav1.ObjectMeta{
Name: "test-example1",
},
Description: "This is an example for testing",
Configuration: v3.PodSecurityAdmissionConfigurationTemplateSpec{
Defaults: v3.PodSecurityAdmissionConfigurationTemplateDefaults{
Enforce: "restricted",
EnforceVersion: "latest",
Audit: "restricted",
AuditVersion: "latest",
Warn: "restricted",
WarnVersion: "latest",
},
Exemptions: v3.PodSecurityAdmissionConfigurationTemplateExemptions{
Usernames: []string{"user-a", "user-b", "user-c"},
RuntimeClasses: []string{"runtime-a", "runtime-b", "runtime-c"},
Namespaces: []string{"ns-a", "ns-b", "ns-c"},
},
},
}
example2 = &v3.PodSecurityAdmissionConfigurationTemplate{
ObjectMeta: metav1.ObjectMeta{
Name: "another-example",
},
Description: "This is another example for testing",
Configuration: v3.PodSecurityAdmissionConfigurationTemplateSpec{
Exemptions: v3.PodSecurityAdmissionConfigurationTemplateExemptions{
Usernames: []string{"user-a", "user-1", "user-2", "user-3"},
RuntimeClasses: []string{"runtime-1", "runtime-2", "runtime-3"},
Namespaces: []string{"ns-1", "ns-2", "ns-3"},
},
},
}
example1plug2 = &v3.PodSecurityAdmissionConfigurationTemplate{
ObjectMeta: metav1.ObjectMeta{
Name: "test-example1",
},
Description: "This is an example for testing",
Configuration: v3.PodSecurityAdmissionConfigurationTemplateSpec{
Defaults: v3.PodSecurityAdmissionConfigurationTemplateDefaults{
Enforce: "restricted",
EnforceVersion: "latest",
Audit: "restricted",
AuditVersion: "latest",
Warn: "restricted",
WarnVersion: "latest",
},
Exemptions: v3.PodSecurityAdmissionConfigurationTemplateExemptions{
Usernames: []string{"user-1", "user-2", "user-3", "user-a", "user-b", "user-c"},
RuntimeClasses: []string{"runtime-1", "runtime-2", "runtime-3", "runtime-a", "runtime-b", "runtime-c"},
Namespaces: []string{"ns-1", "ns-2", "ns-3", "ns-a", "ns-b", "ns-c"},
},
},
}
)

func Test_merge(t *testing.T) {
type args struct {
base *v3.PodSecurityAdmissionConfigurationTemplate
additional *v3.PodSecurityAdmissionConfigurationTemplate
}
tests := []struct {
name string
args args
want *v3.PodSecurityAdmissionConfigurationTemplate
}{
{
name: "base is empty",
args: args{
base: nil,
additional: example1,
},
want: example1,
},
{
name: "additional is empty",
args: args{
base: example1,
additional: nil,
},
want: example1,
},
{
name: "both are empty",
args: args{
base: nil,
additional: nil,
},
want: nil,
},
{
name: "addition contains different exceptions",
args: args{
base: example1,
additional: example2,
},
want: example1plug2,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equalf(t, tt.want, mergeExemptions(tt.args.base, tt.args.additional), "mergeExemptions(%v, %v)", tt.args.base, tt.args.additional)
})
}
}

0 comments on commit 8298de0

Please sign in to comment.