Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove obsolete L2/L3 operator bindings from provisioner #3438

Merged
merged 2 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions components/provisioner/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func (c *config) String() string {
"ProvisioningTimeoutInstallation: %s, ProvisioningTimeoutUpgrade: %s, "+
"DeprovisioningNoInstallTimeoutClusterDeletion: %s, DeprovisioningNoInstallTimeoutWaitingForClusterDeletion: %s "+
"ShootUpgradeTimeout: %s, "+
"OperatorRoleBindingL2SubjectName: %s, OperatorRoleBindingL3SubjectName: %s, OperatorRoleBindingCreatingForAdmin: %t "+
"OperatorRoleBindingCreatingForAdmin: %t "+
"GardenerProject: %s, GardenerKubeconfigPath: %s, GardenerAuditLogsPolicyConfigMap: %s, AuditLogsTenantConfigPath: %s, DefaultEnableIMDSv2: %v"+
"EnqueueInProgressOperations: %v"+
"LogLevel: %s",
Expand All @@ -98,7 +98,7 @@ func (c *config) String() string {
c.ProvisioningTimeout.Installation.String(), c.ProvisioningTimeout.Upgrade.String(),
c.DeprovisioningTimeout.ClusterDeletion.String(), c.DeprovisioningTimeout.WaitingForClusterDeletion.String(),
c.ProvisioningTimeout.ShootUpgrade.String(),
c.OperatorRoleBinding.L2SubjectName, c.OperatorRoleBinding.L3SubjectName, c.OperatorRoleBinding.CreatingForAdmin,
c.OperatorRoleBinding.CreatingForAdmin,
c.Gardener.Project, c.Gardener.KubeconfigPath, c.Gardener.AuditLogsPolicyConfigMap, c.Gardener.AuditLogsTenantConfigPath, c.Gardener.DefaultEnableIMDSv2,
c.EnqueueInProgressOperations,
c.LogLevel)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ func azureGardenerClusterConfigInput(zones ...string) gqlschema.ClusterConfigInp
},
OidcConfig: oidcInput(),
},
Administrators: []string{"testadmin"},
}
}

Expand Down Expand Up @@ -205,6 +206,7 @@ func azureGardenerClusterConfigInputNoSeed(zones ...string) gqlschema.ClusterCon
},
OidcConfig: oidcInput(),
},
Administrators: []string{"testadmin"},
}
}

Expand Down Expand Up @@ -236,6 +238,7 @@ func openStackGardenerClusterConfigInput() gqlschema.ClusterConfigInput {
},
OidcConfig: oidcInput(),
},
Administrators: []string{"testadmin"},
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import (
"context"
"encoding/json"
"fmt"
uuidMocks "github.com/kyma-project/control-plane/components/provisioner/internal/uuid/mocks"
"path/filepath"
"strings"
"testing"
"time"

uuidMocks "github.com/kyma-project/control-plane/components/provisioner/internal/uuid/mocks"

"github.com/kyma-project/control-plane/components/provisioner/internal/api/fake/seeds"
"github.com/kyma-project/control-plane/components/provisioner/internal/api/fake/shoots"
provisioning2 "github.com/kyma-project/control-plane/components/provisioner/internal/operations/stages/provisioning"
Expand Down Expand Up @@ -403,8 +404,7 @@ func testDeprovisioningTimeouts() queue.DeprovisioningTimeouts {

func testOperatorRoleBinding() provisioning2.OperatorRoleBinding {
return provisioning2.OperatorRoleBinding{
L2SubjectName: "runtimeOperator",
L3SubjectName: "runtimeAdmin",
CreatingForAdmin: true,
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,11 @@ import (
)

const (
l2OperatorClusterRoleBindingName = "l2-operator"
l3OperatorClusterRoleBindingName = "l3-operator-admin"
administratorOperatorClusterRoleBindingName = "administrator"

l3OperatorClusterRoleBindingRoleRefName = "cluster-admin"
ownerClusterRoleBindingRoleRefName = "cluster-admin"
ownerClusterRoleBindingRoleRefName = "cluster-admin"

l2OperatorClusterRoleName = "l2-operator"
l2OperatorRulesClusterRoleName = "l2-operator-rules"
l2OperatorBaseRolesLabelKey = "rbac.authorization.k8s.io/aggregate-to-edit"
l2OperatorExtendedRolesLabelKey = "rbac.authorization.k8s.io/aggregate-to-l2-operator"

groupKindSubject = "Group"
userKindSubject = "User"
userKindSubject = "User"
)

//go:generate mockery --name=DynamicKubeconfigProvider
Expand All @@ -45,9 +36,7 @@ type DynamicKubeconfigProvider interface {
}

type OperatorRoleBinding struct {
L2SubjectName string `envconfig:"default=runtimeOperator"`
L3SubjectName string `envconfig:"default=runtimeAdmin"`
CreatingForAdmin bool `envconfig:"default=false"`
CreatingForAdmin bool `envconfig:"default=false"`
}

type CreateBindingsForOperatorsStep struct {
Expand Down Expand Up @@ -103,58 +92,8 @@ func (s *CreateBindingsForOperatorsStep) Run(cluster model.Cluster, _ model.Oper
return operations.StageResult{}, err
}

clusterRoles := make([]v12.ClusterRole, 0)
clusterRoles = append(clusterRoles,
buildClusterRole(
l2OperatorClusterRoleName,
map[string]string{
"app": "kyma",
},
[]metav1.LabelSelector{
{MatchLabels: map[string]string{l2OperatorBaseRolesLabelKey: "true"}},
{MatchLabels: map[string]string{l2OperatorExtendedRolesLabelKey: "true"}},
},
nil,
),
)
clusterRoles = append(clusterRoles,
buildClusterRole(
l2OperatorRulesClusterRoleName,
map[string]string{
"app": "kyma",
l2OperatorExtendedRolesLabelKey: "true",
},
nil,
[]v12.PolicyRule{
{APIGroups: []string{"*"}, Resources: []string{"*"}, Verbs: []string{"get", "list", "watch"}},
},
),
)

clusterRoleBindings := make([]v12.ClusterRoleBinding, 0)

clusterRoleBindings = append(clusterRoleBindings,
buildClusterRoleBinding(
l2OperatorClusterRoleBindingName,
s.operatorRoleBindingConfig.L2SubjectName,
l2OperatorClusterRoleBindingName,
groupKindSubject,
map[string]string{
"app": "kyma",
"reconciler.kyma-project.io/managed-by": "reconciler",
}))

clusterRoleBindings = append(clusterRoleBindings,
buildClusterRoleBinding(
l3OperatorClusterRoleBindingName,
s.operatorRoleBindingConfig.L3SubjectName,
l3OperatorClusterRoleBindingRoleRefName,
groupKindSubject,
map[string]string{
"app": "kyma",
"reconciler.kyma-project.io/managed-by": "reconciler",
}))

if s.operatorRoleBindingConfig.CreatingForAdmin {
for i, administrator := range cluster.Administrators {
clusterRoleBindings = append(clusterRoleBindings,
Expand All @@ -170,10 +109,6 @@ func (s *CreateBindingsForOperatorsStep) Run(cluster model.Cluster, _ model.Oper
}
}

if err := createClusterRoles(k8sClient.RbacV1().ClusterRoles(), clusterRoles); err != nil {
return operations.StageResult{}, err
}

if err := k8sClient.RbacV1().ClusterRoleBindings().DeleteCollection(context.Background(), metav1.DeleteOptions{}, metav1.ListOptions{LabelSelector: "reconciler.kyma-project.io/managed-by=reconciler,app=kyma"}); err != nil {
return operations.StageResult{}, util.K8SErrorToAppError(errors.Wrap(err, "failed to delete cluster role bindings")).SetComponent(apperrors.ErrClusterK8SClient)
}
Expand Down Expand Up @@ -204,39 +139,6 @@ func buildClusterRoleBinding(metaName, subjectName, roleRefName, subjectKind str
}
}

func buildClusterRole(name string, labels map[string]string, aggregationSelectors []metav1.LabelSelector, rules []v12.PolicyRule) v12.ClusterRole {

cr := v12.ClusterRole{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Labels: labels,
},
}
if len(aggregationSelectors) > 0 {
cr.AggregationRule = &v12.AggregationRule{
ClusterRoleSelectors: aggregationSelectors,
}
}

if len(rules) > 0 {
cr.Rules = rules
}

return cr
}

func createClusterRoles(crClient v1.ClusterRoleInterface, clusterRoles []v12.ClusterRole) error {
for _, cr := range clusterRoles {
if _, err := crClient.Create(context.Background(), &cr, metav1.CreateOptions{}); err != nil {
if !k8serrors.IsAlreadyExists(err) {
return util.K8SErrorToAppError(errors.Wrapf(err, "failed to create %s ClusterRole", cr.Name)).SetComponent(apperrors.ErrClusterK8SClient)
}
}
}

return nil
}

func createClusterRoleBindings(crbClient v1.ClusterRoleBindingInterface, clusterRoleBindings ...v12.ClusterRoleBinding) error {
for _, crb := range clusterRoleBindings {
if _, err := crbClient.Create(context.Background(), &crb, metav1.CreateOptions{}); err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import (
)

const dynamicKubeconfig = "dynamic_kubeconfig"
const testAdministrator1 = "testadmin1"
const testAdministrator2 = "testadmin2"

func TestCreateBindingsForOperatorsStep_Run(t *testing.T) {

Expand All @@ -33,11 +35,11 @@ func TestCreateBindingsForOperatorsStep_Run(t *testing.T) {
ClusterConfig: model.GardenerConfig{
Name: "shoot",
},
Administrators: []string{testAdministrator1, testAdministrator2},
}

operatorBindingConfig := OperatorRoleBinding{
L2SubjectName: "l2name",
L3SubjectName: "l3name",
CreatingForAdmin: true,
}

dynamicKubeconfigProvider := &provisioning_mocks.DynamicKubeconfigProvider{}
Expand All @@ -60,36 +62,20 @@ func TestCreateBindingsForOperatorsStep_Run(t *testing.T) {
assert.Equal(t, time.Duration(0), result.Delay)
})

t.Run("should not fail if cluster role already exists", func(t *testing.T) {
// given
k8sClient := fake.NewSimpleClientset()
clusterRole := buildClusterRole(l2OperatorClusterRoleName, map[string]string{"app": "kyma"}, []metav1.LabelSelector{
{MatchLabels: map[string]string{l2OperatorBaseRolesLabelKey: "true"}},
{MatchLabels: map[string]string{l2OperatorExtendedRolesLabelKey: "true"}},
}, nil)
_, err := k8sClient.RbacV1().ClusterRoles().Create(context.Background(), &clusterRole, metav1.CreateOptions{})
require.NoError(t, err)

k8sClientProvider := &mocks.K8sClientProvider{}
k8sClientProvider.On("CreateK8SClient", dynamicKubeconfig).Return(k8sClient, nil)

step := NewCreateBindingsForOperatorsStep(k8sClientProvider, operatorBindingConfig, dynamicKubeconfigProvider, nextStageName, time.Minute)

// when
result, err := step.Run(cluster, model.Operation{}, &logrus.Entry{})

// then
require.NoError(t, err)
assert.Equal(t, nextStageName, result.Stage)
assert.Equal(t, time.Duration(0), result.Delay)
})

t.Run("should not fail if cluster role binding already exists", func(t *testing.T) {
// given
k8sClient := fake.NewSimpleClientset()
clusterRoleBinding := buildClusterRoleBinding(l2OperatorClusterRoleBindingName, operatorBindingConfig.L2SubjectName, l2OperatorClusterRoleName, groupKindSubject, map[string]string{"app": "kyma"})
_, err := k8sClient.RbacV1().ClusterRoleBindings().Create(context.Background(), &clusterRoleBinding, metav1.CreateOptions{})
require.NoError(t, err)
for i, administrator := range cluster.Administrators {
ebensom marked this conversation as resolved.
Show resolved Hide resolved
clusterRoleBinding := buildClusterRoleBinding(
fmt.Sprintf("%s%d", administratorOperatorClusterRoleBindingName, i),
administrator,
ownerClusterRoleBindingRoleRefName,
userKindSubject,
map[string]string{"app": "kyma"},
)
_, err := k8sClient.RbacV1().ClusterRoleBindings().Create(context.Background(), &clusterRoleBinding, metav1.CreateOptions{})
require.NoError(t, err)
}

k8sClientProvider := &mocks.K8sClientProvider{}
k8sClientProvider.On("CreateK8SClient", dynamicKubeconfig).Return(k8sClient, nil)
Expand Down
Loading