package base import ( "context" "fmt" "strings" "github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources" stackerr "github.com/pkg/errors" rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" ) func (r *JenkinsBaseConfigurationReconciler) createRBAC(meta metav1.ObjectMeta) error { err := r.createServiceAccount(meta) if err != nil { return err } role := resources.NewRole(meta) err = r.CreateOrUpdateResource(role) if err != nil { return stackerr.WithStack(err) } roleBinding := resources.NewRoleBinding(meta.Name, meta.Namespace, meta.Name, rbacv1.RoleRef{ APIGroup: "rbac.authorization.k8s.io", Kind: "Role", Name: meta.Name, }) err = r.CreateOrUpdateResource(roleBinding) if err != nil { return stackerr.WithStack(err) } return nil } func (r *JenkinsBaseConfigurationReconciler) ensureExtraRBAC(meta metav1.ObjectMeta) error { var err error var name string for _, roleRef := range r.Configuration.Jenkins.Spec.Roles { name = getExtraRoleBindingName(meta.Name, roleRef) roleBinding := resources.NewRoleBinding(name, meta.Namespace, meta.Name, roleRef) err := r.Client.Create(context.TODO(), roleBinding) if err != nil && errors.IsAlreadyExists(err) { continue } if err != nil { return stackerr.WithStack(err) } } roleBindings := &rbacv1.RoleBindingList{} err = r.Client.List(context.TODO(), roleBindings, client.InNamespace(r.Configuration.Jenkins.Namespace)) if err != nil { return stackerr.WithStack(err) } for _, roleBinding := range roleBindings.Items { if !strings.HasPrefix(roleBinding.Name, getExtraRoleBindingName(meta.Name, rbacv1.RoleRef{Kind: "Role"})) && !strings.HasPrefix(roleBinding.Name, getExtraRoleBindingName(meta.Name, rbacv1.RoleRef{Kind: "ClusterRole"})) { continue } found := false for _, roleRef := range r.Configuration.Jenkins.Spec.Roles { name = getExtraRoleBindingName(meta.Name, roleRef) if roleBinding.Name == name { found = true continue } } if !found { r.logger.Info(fmt.Sprintf("Deleting RoleBinding '%s'", roleBinding.Name)) if err = r.Client.Delete(context.TODO(), &roleBinding); err != nil { return stackerr.WithStack(err) } } } return nil } func getExtraRoleBindingName(serviceAccountName string, roleRef rbacv1.RoleRef) string { var typeName string if roleRef.Kind == "ClusterRole" { typeName = "cr" } else { typeName = "r" } return fmt.Sprintf("%s-%s-%s", serviceAccountName, typeName, roleRef.Name) }