diff --git a/charts/README.md b/charts/README.md index a01fa5173ec..6dc0a3d85d4 100644 --- a/charts/README.md +++ b/charts/README.md @@ -102,6 +102,8 @@ The following table lists the configurable parameters of the latest SMB CSI Driv | `linux.dsName` | name of driver daemonset on linux | `csi-smb-node` | | `linux.dnsPolicy` | dnsPolicy of driver node daemonset, available values: `Default`, `ClusterFirstWithHostNet`, `ClusterFirst` | `ClusterFirstWithHostNet` | | `linux.kubelet` | configure kubelet directory path on Linux agent node node | `/var/lib/kubelet` | +| `linux.krb5CacheDirectory` | directory for kerberos cache on Linux agent node node | `/var/lib/kubelet/kerberos/` | +| `linux.krb5Prefix` | prefix for kerberos cache on Linux agent node node | `krb5cc_` | | `linux.resources.livenessProbe.limits.memory` | liveness-probe memory limits | `100Mi` | | `linux.resources.livenessProbe.requests.cpu` | liveness-probe cpu requests limits | `10m` | | `linux.resources.livenessProbe.requests.memory` | liveness-probe memory requests limits | `20Mi` | diff --git a/charts/latest/csi-driver-smb-v0.0.0.tgz b/charts/latest/csi-driver-smb-v0.0.0.tgz index 74e6d05cc25..29e89a4dfd5 100644 Binary files a/charts/latest/csi-driver-smb-v0.0.0.tgz and b/charts/latest/csi-driver-smb-v0.0.0.tgz differ diff --git a/charts/latest/csi-driver-smb/templates/csi-smb-node.yaml b/charts/latest/csi-driver-smb/templates/csi-smb-node.yaml index 13e8ef72797..22699356208 100755 --- a/charts/latest/csi-driver-smb/templates/csi-smb-node.yaml +++ b/charts/latest/csi-driver-smb/templates/csi-smb-node.yaml @@ -108,6 +108,8 @@ spec: - "--endpoint=$(CSI_ENDPOINT)" - "--nodeid=$(KUBE_NODE_NAME)" - "--enable-get-volume-stats={{ .Values.feature.enableGetVolumeStats }}" + - "--krb5-cache-directory={{ .Values.linux.krb5CacheDirectory }}" + - "--krb5-prefix={{ .Values.linux.krb5Prefix }}" ports: - containerPort: {{ .Values.node.livenessProbe.healthPort }} name: healthz diff --git a/charts/latest/csi-driver-smb/values.yaml b/charts/latest/csi-driver-smb/values.yaml index 35c35fd9054..6e720b64261 100755 --- a/charts/latest/csi-driver-smb/values.yaml +++ b/charts/latest/csi-driver-smb/values.yaml @@ -92,6 +92,8 @@ linux: dsName: csi-smb-node # daemonset name dnsPolicy: ClusterFirstWithHostNet # available values: Default, ClusterFirstWithHostNet, ClusterFirst kubelet: /var/lib/kubelet + krb5CacheDirectory: /var/lib/kubelet/kerberos/ # directory for kerberos credential cache + krb5Prefix: "krb5cc_" # prefix for kerberos credential cache tolerations: - operator: "Exists" resources: diff --git a/cmd/smbplugin/main.go b/cmd/smbplugin/main.go index 157cba6ee73..344281336e7 100644 --- a/cmd/smbplugin/main.go +++ b/cmd/smbplugin/main.go @@ -45,6 +45,8 @@ var ( removeSMBMappingDuringUnmount = flag.Bool("remove-smb-mapping-during-unmount", true, "remove SMBMapping during unmount on Windows node") workingMountDir = flag.String("working-mount-dir", "/tmp", "working directory for provisioner to mount smb shares temporarily") volStatsCacheExpireInMinutes = flag.Int("vol-stats-cache-expire-in-minutes", 10, "The cache expire time in minutes for volume stats cache") + krb5CacheDirectory = flag.String("krb5-cache-directory", "/var/lib/kubelet/kerberos/", "The directory for kerberos cache") + krb5Prefix = flag.String("krb5-prefix", "krb5cc_", "The prefix for kerberos cache") ) func main() { @@ -74,6 +76,8 @@ func handle() { RemoveSMBMappingDuringUnmount: *removeSMBMappingDuringUnmount, WorkingMountDir: *workingMountDir, VolStatsCacheExpireInMinutes: *volStatsCacheExpireInMinutes, + Krb5CacheDirectory: *krb5CacheDirectory, + Krb5Prefix: *krb5Prefix, } driver := smb.NewDriver(&driverOptions) driver.Run(*endpoint, *kubeconfig, false) diff --git a/pkg/smb/nodeserver.go b/pkg/smb/nodeserver.go index 3cf93359811..5bc75879cd7 100644 --- a/pkg/smb/nodeserver.go +++ b/pkg/smb/nodeserver.go @@ -186,7 +186,7 @@ func (d *Driver) NodeStageVolume(_ context.Context, req *csi.NodeStageVolumeRequ sensitiveMountOptions = []string{password} } } else { - var useKerberosCache, err = ensureKerberosCache(volumeID, mountFlags, secrets) + var useKerberosCache, err = ensureKerberosCache(d.krb5CacheDirectory, d.krb5Prefix, volumeID, mountFlags, secrets) if err != nil { return nil, status.Error(codes.Internal, fmt.Sprintf("Error writing kerberos cache: %v", err)) } @@ -264,7 +264,7 @@ func (d *Driver) NodeUnstageVolume(_ context.Context, req *csi.NodeUnstageVolume return nil, status.Errorf(codes.Internal, "failed to unmount staging target %q: %v", stagingTargetPath, err) } - if err := deleteKerberosCache(volumeID); err != nil { + if err := deleteKerberosCache(d.krb5CacheDirectory, volumeID); err != nil { return nil, status.Errorf(codes.Internal, "failed to delete kerberos cache: %v", err) } @@ -469,12 +469,12 @@ func getCredUID(mountFlags []string) (int, error) { return -1, fmt.Errorf("Can't find credUid in mount flags") } -func getKrb5CcacheName(credUID int) string { +func getKrb5CcacheName(krb5Prefix string, credUID int) string { return fmt.Sprintf("%s%d", krb5Prefix, credUID) } // returns absolute path for name of file inside krb5CacheDirectory -func getKerberosFilePath(fileName string) string { +func getKerberosFilePath(krb5CacheDirectory, fileName string) string { return fmt.Sprintf("%s%s", krb5CacheDirectory, fileName) } @@ -483,7 +483,7 @@ func volumeKerberosCacheName(volumeID string) string { return strings.ReplaceAll(strings.ReplaceAll(encoded, "/", "-"), "+", "_") } -func kerberosCacheDirectoryExists() (bool, error) { +func kerberosCacheDirectoryExists(krb5CacheDirectory string) (bool, error) { _, err := os.Stat(krb5CacheDirectory) if os.IsNotExist(err) { return false, status.Error(codes.Internal, fmt.Sprintf("Directory for kerberos caches must exist, it will not be created: %s: %v", krb5CacheDirectory, err)) @@ -493,8 +493,8 @@ func kerberosCacheDirectoryExists() (bool, error) { return true, nil } -func getKerberosCache(credUID int, secrets map[string]string) (string, []byte, error) { - var krb5CcacheName = getKrb5CcacheName(credUID) +func getKerberosCache(krb5CacheDirectory, krb5Prefix string, credUID int, secrets map[string]string) (string, []byte, error) { + var krb5CcacheName = getKrb5CcacheName(krb5Prefix, credUID) var krb5CcacheContent string for k, v := range secrets { switch strings.ToLower(k) { @@ -509,7 +509,7 @@ func getKerberosCache(credUID int, secrets map[string]string) (string, []byte, e if err != nil { return "", nil, status.Error(codes.InvalidArgument, fmt.Sprintf("Malformed kerberos cache in key %s, expected to be in base64 form: %v", krb5CcacheName, err)) } - var krb5CacheFileName = getKerberosFilePath(getKrb5CcacheName(credUID)) + var krb5CacheFileName = getKerberosFilePath(krb5CacheDirectory, getKrb5CcacheName(krb5Prefix, credUID)) return krb5CacheFileName, content, nil } @@ -517,10 +517,10 @@ func getKerberosCache(credUID int, secrets map[string]string) (string, []byte, e // Create kerberos cache in the file based on the VolumeID, so it can be cleaned up during unstage // At the same time, kerberos expects to find cache in file named "krb5cc_*", so creating symlink // will allow both clean up and serving proper cache to the kerberos. -func ensureKerberosCache(volumeID string, mountFlags []string, secrets map[string]string) (bool, error) { +func ensureKerberosCache(krb5CacheDirectory, krb5Prefix, volumeID string, mountFlags []string, secrets map[string]string) (bool, error) { var securityIsKerberos = hasKerberosMountOption(mountFlags) if securityIsKerberos { - _, err := kerberosCacheDirectoryExists() + _, err := kerberosCacheDirectoryExists(krb5CacheDirectory) if err != nil { return false, err } @@ -528,14 +528,14 @@ func ensureKerberosCache(volumeID string, mountFlags []string, secrets map[strin if err != nil { return false, err } - krb5CacheFileName, content, err := getKerberosCache(credUID, secrets) + krb5CacheFileName, content, err := getKerberosCache(krb5CacheDirectory, krb5Prefix, credUID, secrets) if err != nil { return false, err } // Write cache into volumeId-based filename, so it can be cleaned up later volumeIDCacheFileName := volumeKerberosCacheName(volumeID) - volumeIDCacheAbsolutePath := getKerberosFilePath(volumeIDCacheFileName) + volumeIDCacheAbsolutePath := getKerberosFilePath(krb5CacheDirectory, volumeIDCacheFileName) if err := os.WriteFile(volumeIDCacheAbsolutePath, content, os.FileMode(0700)); err != nil { return false, status.Error(codes.Internal, fmt.Sprintf("Couldn't write kerberos cache to file %s: %v", volumeIDCacheAbsolutePath, err)) } @@ -561,8 +561,8 @@ func ensureKerberosCache(volumeID string, mountFlags []string, secrets map[strin return false, nil } -func deleteKerberosCache(volumeID string) error { - exists, err := kerberosCacheDirectoryExists() +func deleteKerberosCache(krb5CacheDirectory, volumeID string) error { + exists, err := kerberosCacheDirectoryExists(krb5CacheDirectory) // If not supported, simply return if !exists { return nil @@ -573,7 +573,7 @@ func deleteKerberosCache(volumeID string) error { volumeIDCacheFileName := volumeKerberosCacheName(volumeID) - var volumeIDCacheAbsolutePath = getKerberosFilePath(volumeIDCacheFileName) + var volumeIDCacheAbsolutePath = getKerberosFilePath(krb5CacheDirectory, volumeIDCacheFileName) _, err = os.Stat(volumeIDCacheAbsolutePath) // Not created or already removed if os.IsNotExist(err) { @@ -585,7 +585,7 @@ func deleteKerberosCache(volumeID string) error { // If file with cache exists, full clean means removing symlinks to the file. dirEntries, _ := os.ReadDir(krb5CacheDirectory) for _, dirEntry := range dirEntries { - filePath := getKerberosFilePath(dirEntry.Name()) + filePath := getKerberosFilePath(krb5CacheDirectory, dirEntry.Name()) lStat, _ := os.Lstat(filePath) // If it's a symlink, checking if it's pointing to the volume file in question if lStat != nil { diff --git a/pkg/smb/nodeserver_test.go b/pkg/smb/nodeserver_test.go index fa857986675..c7531f29253 100644 --- a/pkg/smb/nodeserver_test.go +++ b/pkg/smb/nodeserver_test.go @@ -800,6 +800,8 @@ func TestGetKerberosCache(t *testing.T) { ticket := []byte{'G', 'O', 'L', 'A', 'N', 'G'} base64Ticket := base64.StdEncoding.EncodeToString(ticket) credUID := 1000 + krb5CacheDirectory := "/var/lib/kubelet/kerberos/" + krb5Prefix := "krb5cc_" goodFileName := fmt.Sprintf("%s%s%d", krb5CacheDirectory, krb5Prefix, credUID) krb5CcacheName := "krb5cc_1000" @@ -855,7 +857,7 @@ func TestGetKerberosCache(t *testing.T) { } for _, test := range tests { - fileName, content, err := getKerberosCache(test.credUID, test.secrets) + fileName, content, err := getKerberosCache(krb5CacheDirectory, krb5Prefix, test.credUID, test.secrets) if !reflect.DeepEqual(err, test.expectedErr) { t.Errorf("[%s]: Expected error : %v, Actual error: %v", test.desc, test.expectedErr, err) } else { diff --git a/pkg/smb/smb.go b/pkg/smb/smb.go index 0ca46171709..c768cd16b02 100644 --- a/pkg/smb/smb.go +++ b/pkg/smb/smb.go @@ -38,8 +38,6 @@ const ( sourceField = "source" subDirField = "subdir" domainField = "domain" - krb5Prefix = "krb5cc_" - krb5CacheDirectory = "/var/lib/kubelet/kerberos/" mountOptionsField = "mountoptions" defaultDomainName = "AZURE" pvcNameKey = "csi.storage.k8s.io/pvc/name" @@ -59,6 +57,8 @@ type DriverOptions struct { RemoveSMBMappingDuringUnmount bool WorkingMountDir string VolStatsCacheExpireInMinutes int + Krb5CacheDirectory string + Krb5Prefix string } // Driver implements all interfaces of CSI drivers @@ -74,6 +74,8 @@ type Driver struct { volStatsCache azcache.Resource // this only applies to Windows node removeSMBMappingDuringUnmount bool + krb5CacheDirectory string + krb5Prefix string } // NewDriver Creates a NewCSIDriver object. Assumes vendor version is equal to driver version & @@ -86,6 +88,8 @@ func NewDriver(options *DriverOptions) *Driver { driver.enableGetVolumeStats = options.EnableGetVolumeStats driver.removeSMBMappingDuringUnmount = options.RemoveSMBMappingDuringUnmount driver.workingMountDir = options.WorkingMountDir + driver.krb5CacheDirectory = options.Krb5CacheDirectory + driver.krb5Prefix = options.Krb5Prefix driver.volumeLocks = newVolumeLocks() if options.VolStatsCacheExpireInMinutes <= 0 {