Skip to content

Commit e6fda73

Browse files
authored
Support useNodeAuthorization option to specify whether or not to use node authorized client for CSI (#4494)
Signed-off-by: trafalgarzzz <trafalgarz@outlook.com>
1 parent 841eb35 commit e6fda73

5 files changed

Lines changed: 70 additions & 19 deletions

File tree

charts/fluid/fluid/templates/csi/daemonset.yaml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ spec:
112112
- name: fluid-src-dir
113113
mountPath: {{ .Values.runtime.mountRoot | quote }}
114114
mountPropagation: "HostToContainer"
115+
{{- if .Values.csi.useNodeAuthorization }}
115116
- name: kubelet-kube-config
116117
mountPath: /etc/kubernetes/kubelet.conf
117118
mountPropagation: "HostToContainer"
@@ -123,6 +124,7 @@ spec:
123124
mountPath: {{ .Values.csi.kubelet.certDir | quote }}
124125
readOnly: true
125126
{{- end }}
127+
{{- end }}
126128
- name: updatedb-conf
127129
mountPath: /host-etc/updatedb.conf
128130
- name: updatedb-conf-bak
@@ -132,12 +134,19 @@ spec:
132134
hostPath:
133135
path: {{ .Values.csi.kubelet.rootDir | quote }}
134136
type: Directory
137+
{{- if .Values.csi.useNodeAuthorization }}
138+
{{- $kubeletRootDir := ternary ( .Values.csi.kubelet.rootDir ) ( print .Values.csi.kubelet.rootDir "/" ) ( hasSuffix "/" .Values.csi.kubelet.rootDir ) }}
135139
{{- if not ( hasPrefix $kubeletRootDir .Values.csi.kubelet.certDir ) }}
136140
- name: kubelet-cert-dir
137141
hostPath:
138142
path: {{ .Values.csi.kubelet.certDir | quote }}
139143
type: Directory
140144
{{- end }}
145+
- name: kubelet-kube-config
146+
hostPath:
147+
path: {{ .Values.csi.kubelet.kubeConfigFile | quote }}
148+
type: File
149+
{{- end }}
141150
- name: plugin-dir
142151
hostPath:
143152
path: {{ .Values.csi.kubelet.rootDir }}/plugins/csi-fluid-plugin
@@ -150,10 +159,6 @@ spec:
150159
path: {{ .Values.runtime.mountRoot | quote }}
151160
type: DirectoryOrCreate
152161
name: fluid-src-dir
153-
- hostPath:
154-
path: {{ .Values.csi.kubelet.kubeConfigFile | quote }}
155-
type: File
156-
name: kubelet-kube-config
157162
- hostPath:
158163
path: /etc/updatedb.conf
159164
type: FileOrCreate

charts/fluid/fluid/templates/role/csi/rbac.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ rules:
4444
- apiGroups: [""]
4545
resources: ["events"]
4646
verbs: ["create", "patch"]
47+
{{- if not .Values.csi.useNodeAuthorization }}
48+
- apiGroups: [""]
49+
resources: ["nodes"]
50+
verbs: ["get", "patch"]
51+
{{- end }}
4752
---
4853
kind: ClusterRoleBinding
4954
apiVersion: rbac.authorization.k8s.io/v1

charts/fluid/fluid/values.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ csi:
5858
imagePrefix: *defaultImagePrefix
5959
imageName: fluid-csi
6060
imageTag: *defaultVersion
61+
# Whether or not to borrow kubelet's config file to use node authorization to restrict CSI Plugin's permission
62+
# See why Fluid's CSI Plugins need node-specific authorization at https://github.com/fluid-cloudnative/fluid/security/advisories/GHSA-93xx-cvmc-9w3v
63+
# See node authorization at https://kubernetes.io/docs/reference/access-authn-authz/node/
64+
useNodeAuthorization: true
6165
kubelet:
6266
kubeConfigFile: /etc/kubernetes/kubelet.conf
6367
certDir: /var/lib/kubelet/pki

pkg/csi/plugins/nodeserver.go

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ import (
3232
"github.com/fluid-cloudnative/fluid/pkg/utils"
3333
"github.com/fluid-cloudnative/fluid/pkg/utils/cmdguard"
3434
"github.com/fluid-cloudnative/fluid/pkg/utils/dataset/volume"
35+
"github.com/fluid-cloudnative/fluid/pkg/utils/kubeclient"
3536
"github.com/pkg/errors"
36-
v1 "k8s.io/api/core/v1"
37+
corev1 "k8s.io/api/core/v1"
3738
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3839
"k8s.io/apimachinery/pkg/types"
3940
"k8s.io/apimachinery/pkg/util/wait"
@@ -60,7 +61,7 @@ type nodeServer struct {
6061
apiReader client.Reader
6162
nodeAuthorizedClient *kubernetes.Clientset
6263
locks *utils.VolumeLocks
63-
node *v1.Node
64+
node *corev1.Node
6465
}
6566

6667
func (ns *nodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error) {
@@ -464,7 +465,7 @@ func (ns *nodeServer) getRuntimeNamespacedName(volumeContext map[string]string,
464465
}
465466

466467
// getNode first checks cached node
467-
func (ns *nodeServer) getNode() (node *v1.Node, err error) {
468+
func (ns *nodeServer) getNode() (node *corev1.Node, err error) {
468469
// Default to allow patch stale node info
469470
if envVar, found := os.LookupEnv(AllowPatchStaleNodeEnv); !found || envVar == "true" {
470471
if ns.node != nil {
@@ -473,20 +474,23 @@ func (ns *nodeServer) getNode() (node *v1.Node, err error) {
473474
}
474475
}
475476

476-
if node, err = ns.nodeAuthorizedClient.CoreV1().Nodes().Get(context.TODO(), ns.nodeId, metav1.GetOptions{}); err != nil {
477-
return nil, err
477+
useNodeAuthorization := ns.nodeAuthorizedClient != nil
478+
if useNodeAuthorization {
479+
if node, err = ns.nodeAuthorizedClient.CoreV1().Nodes().Get(context.TODO(), ns.nodeId, metav1.GetOptions{}); err != nil {
480+
return nil, err
481+
}
482+
} else {
483+
if node, err = kubeclient.GetNode(ns.apiReader, ns.nodeId); err != nil {
484+
return nil, err
485+
}
478486
}
479487

480-
// if node, err = kubeclient.GetNode(ns.apiReader, ns.nodeId); err != nil {
481-
// return nil, err
482-
// }
483-
484488
glog.V(1).Infof("Got node %s from api server", node.Name)
485489
ns.node = node
486490
return ns.node, nil
487491
}
488492

489-
func (ns *nodeServer) patchNodeWithLabel(node *v1.Node, labelsToModify common.LabelsToModify) error {
493+
func (ns *nodeServer) patchNodeWithLabel(node *corev1.Node, labelsToModify common.LabelsToModify) error {
490494
labels := labelsToModify.GetLabels()
491495
labelValuePair := map[string]interface{}{}
492496

@@ -516,10 +520,22 @@ func (ns *nodeServer) patchNodeWithLabel(node *v1.Node, labelsToModify common.La
516520
if err != nil {
517521
return err
518522
}
519-
520-
_, err = ns.nodeAuthorizedClient.CoreV1().Nodes().Patch(context.TODO(), node.Name, types.StrategicMergePatchType, patchByteData, metav1.PatchOptions{})
521-
if err != nil {
522-
return err
523+
useNodeAuthorization := ns.nodeAuthorizedClient != nil
524+
if useNodeAuthorization {
525+
_, err = ns.nodeAuthorizedClient.CoreV1().Nodes().Patch(context.TODO(), node.Name, types.StrategicMergePatchType, patchByteData, metav1.PatchOptions{})
526+
if err != nil {
527+
return err
528+
}
529+
} else {
530+
nodeToPatch := &corev1.Node{
531+
ObjectMeta: metav1.ObjectMeta{
532+
Name: node.Name,
533+
},
534+
}
535+
err = ns.client.Patch(context.TODO(), nodeToPatch, client.RawPatch(types.StrategicMergePatchType, patchByteData))
536+
if err != nil {
537+
return err
538+
}
523539
}
524540

525541
return nil

pkg/csi/plugins/register.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,35 @@ limitations under the License.
1717
package plugins
1818

1919
import (
20+
"os"
21+
2022
"github.com/fluid-cloudnative/fluid/pkg/csi/config"
2123
"github.com/fluid-cloudnative/fluid/pkg/utils/kubelet"
24+
"github.com/golang/glog"
25+
"github.com/pkg/errors"
26+
"k8s.io/client-go/kubernetes"
2227
"sigs.k8s.io/controller-runtime/pkg/manager"
2328
)
2429

30+
// getNodeAuthorizedClientFromKubeletConfig retrieves a node-authorized Kubernetes client from the Kubelet configuration file.
31+
// This function checks if the specified Kubelet configuration file exists. If the file does not exist, it returns an empty client without an error .
32+
// If the file exists, it attempts to initialize and return a node-authorized Kubernetes client.
33+
func getNodeAuthorizedClientFromKubeletConfig(kubeletConfigPath string) (*kubernetes.Clientset, error) {
34+
_, err := os.Stat(kubeletConfigPath)
35+
if err != nil {
36+
if os.IsNotExist(err) {
37+
glog.Warningf("kubelet config file %s not exists, continue without node authorization...", kubeletConfigPath)
38+
return nil, nil
39+
}
40+
return nil, errors.Wrapf(err, "fail to stat kubelet config file %s", kubeletConfigPath)
41+
}
42+
43+
return kubelet.InitNodeAuthorizedClient(kubeletConfigPath)
44+
}
45+
2546
// Register initializes the csi driver and registers it to the controller manager.
2647
func Register(mgr manager.Manager, ctx config.RunningContext) error {
27-
client, err := kubelet.InitNodeAuthorizedClient(ctx.KubeletConfigPath)
48+
client, err := getNodeAuthorizedClientFromKubeletConfig(ctx.KubeletConfigPath)
2849
if err != nil {
2950
return err
3051
}

0 commit comments

Comments
 (0)