Merge pull request #3953 from Vacant2333/add_rbac_task_when_karmada_operator_init

Feat: Add rbac task when karmada operator init
This commit is contained in:
karmada-bot 2023-08-30 17:27:09 +08:00 committed by GitHub
commit 9003c83fc2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 249 additions and 9 deletions

View File

@ -48,7 +48,7 @@ spec:
- --cluster-name=karmada - --cluster-name=karmada
- --cluster-signing-cert-file=/etc/karmada/pki/ca.crt - --cluster-signing-cert-file=/etc/karmada/pki/ca.crt
- --cluster-signing-key-file=/etc/karmada/pki/ca.key - --cluster-signing-key-file=/etc/karmada/pki/ca.key
- --controllers=namespace,garbagecollector,serviceaccount-token,ttl-after-finished,bootstrapsigner,csrapproving,csrcleaner,csrsigning - --controllers=namespace,garbagecollector,serviceaccount-token,ttl-after-finished,bootstrapsigner,csrapproving,csrcleaner,csrsigning,clusterrole-aggregation
- --leader-elect=true - --leader-elect=true
- --node-cidr-mask-size=24 - --node-cidr-mask-size=24
- --root-ca-file=/etc/karmada/pki/ca.crt - --root-ca-file=/etc/karmada/pki/ca.crt

View File

@ -77,6 +77,7 @@ func NewInitJob(opt *InitOptions) *workflow.Job {
initJob.AppendTask(tasks.NewKarmadaAggregatedApiserverTask()) initJob.AppendTask(tasks.NewKarmadaAggregatedApiserverTask())
initJob.AppendTask(tasks.NewCheckApiserverHealthTask()) initJob.AppendTask(tasks.NewCheckApiserverHealthTask())
initJob.AppendTask(tasks.NewKarmadaResourcesTask()) initJob.AppendTask(tasks.NewKarmadaResourcesTask())
initJob.AppendTask(tasks.NewRBACTask())
initJob.AppendTask(tasks.NewComponentTask()) initJob.AppendTask(tasks.NewComponentTask())
initJob.AppendTask(tasks.NewWaitControlPlaneTask()) initJob.AppendTask(tasks.NewWaitControlPlaneTask())

View File

@ -55,10 +55,7 @@ func aggregatedAPIService(client *aggregator.Clientset, name, namespace string)
return fmt.Errorf("err when decoding AggregatedApiserver APIService: %w", err) return fmt.Errorf("err when decoding AggregatedApiserver APIService: %w", err)
} }
if err := apiclient.CreateOrUpdateAPIService(client, apiService); err != nil { return apiclient.CreateOrUpdateAPIService(client, apiService)
return err
}
return nil
} }
func aggregatedApiserverService(client clientset.Interface, name, namespace string) error { func aggregatedApiserverService(client clientset.Interface, name, namespace string) error {
@ -78,10 +75,7 @@ func aggregatedApiserverService(client clientset.Interface, name, namespace stri
return fmt.Errorf("err when decoding AggregatedApiserver Service: %w", err) return fmt.Errorf("err when decoding AggregatedApiserver Service: %w", err)
} }
if err := apiclient.CreateOrUpdateService(client, aggregatedService); err != nil { return apiclient.CreateOrUpdateService(client, aggregatedService)
return err
}
return nil
} }
// EnsureMetricsAdapterAPIService creates APIService and a service for karmada-metrics-adapter // EnsureMetricsAdapterAPIService creates APIService and a service for karmada-metrics-adapter

View File

@ -0,0 +1,154 @@
package rbac
const (
// KarmadaResourceViewClusterRole clusterrole for view karmada resources
KarmadaResourceViewClusterRole = `
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
# refer to https://kubernetes.io/docs/reference/access-authn-authz/rbac/#auto-reconciliation
# and https://kubernetes.io/docs/reference/access-authn-authz/rbac/#kubectl-auth-reconcile
rbac.authorization.kubernetes.io/autoupdate: "true"
labels:
# refer to https://kubernetes.io/docs/reference/access-authn-authz/rbac/#default-roles-and-role-bindings
kubernetes.io/bootstrapping: rbac-defaults
# used to aggregate rules to view clusterrole
rbac.authorization.k8s.io/aggregate-to-view: "true"
name: karmada-view
rules:
- apiGroups:
- "autoscaling.karmada.io"
resources:
- cronfederatedhpas
- cronfederatedhpas/status
- federatedhpas
- federatedhpas/status
verbs:
- get
- list
- watch
- apiGroups:
- "multicluster.x-k8s.io"
resources:
- serviceexports
- serviceexports/status
- serviceimports
- serviceimports/status
verbs:
- get
- list
- watch
- apiGroups:
- "networking.karmada.io"
resources:
- multiclusteringresses
- multiclusteringresses/status
- multiclusterservices
- multiclusterservices/status
verbs:
- get
- list
- watch
- apiGroups:
- "policy.karmada.io"
resources:
- overridepolicies
- propagationpolicies
verbs:
- get
- list
- watch
- apiGroups:
- "work.karmada.io"
resources:
- resourcebindings
- resourcebindings/status
- works
- works/status
verbs:
- get
- list
- watch
`
// KarmadaResourceEditClusterRole clusterrole for edit karmada resources
KarmadaResourceEditClusterRole = `
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
# refer to https://kubernetes.io/docs/reference/access-authn-authz/rbac/#auto-reconciliation
# and https://kubernetes.io/docs/reference/access-authn-authz/rbac/#kubectl-auth-reconcile
rbac.authorization.kubernetes.io/autoupdate: "true"
labels:
# refer to https://kubernetes.io/docs/reference/access-authn-authz/rbac/#default-roles-and-role-bindings
kubernetes.io/bootstrapping: rbac-defaults
# used to aggregate rules to view clusterrole
rbac.authorization.k8s.io/aggregate-to-edit: "true"
name: karmada-edit
rules:
- apiGroups:
- "autoscaling.karmada.io"
resources:
- cronfederatedhpas
- cronfederatedhpas/status
- federatedhpas
- federatedhpas/status
verbs:
- create
- delete
- deletecollection
- patch
- update
- apiGroups:
- "multicluster.x-k8s.io"
resources:
- serviceexports
- serviceexports/status
- serviceimports
- serviceimports/status
verbs:
- create
- delete
- deletecollection
- patch
- update
- apiGroups:
- "networking.karmada.io"
resources:
- multiclusteringresses
- multiclusteringresses/status
- multiclusterservices
- multiclusterservices/status
verbs:
- create
- delete
- deletecollection
- patch
- update
- apiGroups:
- "policy.karmada.io"
resources:
- overridepolicies
- propagationpolicies
verbs:
- create
- delete
- deletecollection
- patch
- update
- apiGroups:
- "work.karmada.io"
resources:
- resourcebindings
- resourcebindings/status
- works
- works/status
verbs:
- create
- delete
- deletecollection
- patch
- update
`
)

View File

@ -0,0 +1,36 @@
package rbac
import (
"fmt"
rbacv1 "k8s.io/api/rbac/v1"
kuberuntime "k8s.io/apimachinery/pkg/runtime"
clientset "k8s.io/client-go/kubernetes"
clientsetscheme "k8s.io/client-go/kubernetes/scheme"
"github.com/karmada-io/karmada/operator/pkg/util/apiclient"
)
// EnsureKarmadaRBAC create karmada resource view and edit clusterrole
func EnsureKarmadaRBAC(client clientset.Interface) error {
if err := grantKarmadaResourceViewClusterrole(client); err != nil {
return err
}
return grantKarmadaResourceEditClusterrole(client)
}
func grantKarmadaResourceViewClusterrole(client clientset.Interface) error {
viewClusterrole := &rbacv1.ClusterRole{}
if err := kuberuntime.DecodeInto(clientsetscheme.Codecs.UniversalDecoder(), []byte(KarmadaResourceViewClusterRole), viewClusterrole); err != nil {
return fmt.Errorf("err when decoding Karmada view Clusterrole: %w", err)
}
return apiclient.CreateOrUpdateClusterRole(client, viewClusterrole)
}
func grantKarmadaResourceEditClusterrole(client clientset.Interface) error {
editClusterrole := &rbacv1.ClusterRole{}
if err := kuberuntime.DecodeInto(clientsetscheme.Codecs.UniversalDecoder(), []byte(KarmadaResourceEditClusterRole), editClusterrole); err != nil {
return fmt.Errorf("err when decoding Karmada edit Clusterrole: %w", err)
}
return apiclient.CreateOrUpdateClusterRole(client, editClusterrole)
}

View File

@ -0,0 +1,29 @@
package tasks
import (
"errors"
"k8s.io/klog/v2"
"github.com/karmada-io/karmada/operator/pkg/karmadaresource/rbac"
"github.com/karmada-io/karmada/operator/pkg/workflow"
)
// NewRBACTask init a RBAC task, it will create clusterrole for view/edit karmada resources
func NewRBACTask() workflow.Task {
return workflow.Task{
Name: "rbac",
Run: runRBAC,
}
}
func runRBAC(r workflow.RunData) error {
data, ok := r.(InitData)
if !ok {
return errors.New("RBAC task invoked with an invalid data struct")
}
klog.V(4).InfoS("[RBAC] Running rbac task", "karmada", klog.KObj(data))
return rbac.EnsureKarmadaRBAC(data.KarmadaClient())
}

View File

@ -8,6 +8,7 @@ import (
admissionregistrationv1 "k8s.io/api/admissionregistration/v1" admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
appsv1 "k8s.io/api/apps/v1" appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
crdsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" crdsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
@ -230,6 +231,31 @@ func CreateOrUpdateStatefulSet(client clientset.Interface, statefulSet *appsv1.S
return nil return nil
} }
// CreateOrUpdateClusterRole creates a Clusterrole if the target resource doesn't exist. If the resource exists already, this function will update the resource instead.
func CreateOrUpdateClusterRole(client clientset.Interface, clusterrole *rbacv1.ClusterRole) error {
_, err := client.RbacV1().ClusterRoles().Create(context.TODO(), clusterrole, metav1.CreateOptions{})
if err != nil {
if !apierrors.IsAlreadyExists(err) {
return err
}
older, err := client.RbacV1().ClusterRoles().Get(context.TODO(), clusterrole.GetName(), metav1.GetOptions{})
if err != nil {
return err
}
clusterrole.ResourceVersion = older.ResourceVersion
_, err = client.RbacV1().ClusterRoles().Update(context.TODO(), clusterrole, metav1.UpdateOptions{})
if err != nil {
return err
}
}
klog.V(4).InfoS("Successfully created or updated clusterrole", "clusterrole", clusterrole.GetName)
return nil
}
// DeleteDeploymentIfHasLabels deletes a Deployment that exists the given labels. // DeleteDeploymentIfHasLabels deletes a Deployment that exists the given labels.
func DeleteDeploymentIfHasLabels(client clientset.Interface, name, namespace string, ls labels.Set) error { func DeleteDeploymentIfHasLabels(client clientset.Interface, name, namespace string, ls labels.Set) error {
deployment, err := client.AppsV1().Deployments(namespace).Get(context.TODO(), name, metav1.GetOptions{}) deployment, err := client.AppsV1().Deployments(namespace).Get(context.TODO(), name, metav1.GetOptions{})