@@ -76,8 +76,7 @@ func (d *Driver) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolu
7676 mountPermissions := d .mountPermissions
7777 context := req .GetVolumeContext ()
7878 if context != nil {
79- // token request
80- if getValueInMap (context , serviceAccountTokenField ) != "" && getValueInMap (context , clientIDField ) != "" {
79+ if ! strings .EqualFold (getValueInMap (context , mountWithManagedIdentityField ), trueValue ) && getValueInMap (context , serviceAccountTokenField ) != "" && getValueInMap (context , clientIDField ) != "" {
8180 klog .V (2 ).Infof ("NodePublishVolume: volume(%s) mount on %s with service account token, clientID: %s" , volumeID , target , getValueInMap (context , clientIDField ))
8281 _ , err := d .NodeStageVolume (ctx , & csi.NodeStageVolumeRequest {
8382 StagingTargetPath : target ,
@@ -248,7 +247,7 @@ func (d *Driver) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRe
248247 volumeID := req .GetVolumeId ()
249248 context := req .GetVolumeContext ()
250249
251- if getValueInMap (context , clientIDField ) != "" && getValueInMap (context , serviceAccountTokenField ) == "" {
250+ if getValueInMap (context , clientIDField ) != "" && ! strings . EqualFold ( getValueInMap ( context , mountWithManagedIdentityField ), trueValue ) && getValueInMap (context , serviceAccountTokenField ) == "" {
252251 klog .V (2 ).Infof ("Skip NodeStageVolume for volume(%s) since clientID %s is provided but service account token is empty" , volumeID , getValueInMap (context , clientIDField ))
253252 return & csi.NodeStageVolumeResponse {}, nil
254253 }
@@ -277,8 +276,8 @@ func (d *Driver) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRe
277276 }
278277 // don't respect fsType from req.GetVolumeCapability().GetMount().GetFsType()
279278 // since it's ext4 by default on Linux
280- var fsType , server , protocol , ephemeralVolMountOptions , storageEndpointSuffix , folderName string
281- var ephemeralVol , createFolderIfNotExist , encryptInTransit bool
279+ var fsType , server , protocol , ephemeralVolMountOptions , storageEndpointSuffix , folderName , clientID string
280+ var ephemeralVol , createFolderIfNotExist , encryptInTransit , mountWithManagedIdentity bool
282281 fileShareNameReplaceMap := map [string ]string {}
283282
284283 mountPermissions := d .mountPermissions
@@ -314,7 +313,6 @@ func (d *Driver) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRe
314313 fileShareNameReplaceMap [pvNameMetadata ] = v
315314 case mountPermissionsField :
316315 if v != "" {
317- var err error
318316 var perm uint64
319317 if perm , err = strconv .ParseUint (v , 8 , 32 ); err != nil {
320318 return nil , status .Errorf (codes .InvalidArgument , "invalid mountPermissions %s" , v )
@@ -326,11 +324,17 @@ func (d *Driver) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRe
326324 }
327325 }
328326 case encryptInTransitField :
329- var err error
330327 encryptInTransit , err = strconv .ParseBool (v )
331328 if err != nil {
332329 return nil , status .Error (codes .InvalidArgument , fmt .Sprintf ("Volume context property %q must be a boolean value: %v" , k , err ))
333330 }
331+ case mountWithManagedIdentityField :
332+ mountWithManagedIdentity , err = strconv .ParseBool (v )
333+ if err != nil {
334+ return nil , status .Error (codes .InvalidArgument , fmt .Sprintf ("Volume context property %q must be a boolean value: %v" , k , err ))
335+ }
336+ case clientIDField :
337+ clientID = v
334338 }
335339 }
336340
@@ -401,18 +405,29 @@ func (d *Driver) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRe
401405 mountOptions = util .JoinMountOptions (mountFlags , []string {"vers=4,minorversion=1,sec=sys" })
402406 mountOptions = appendDefaultNfsMountOptions (mountOptions , d .appendNoResvPortOption , d .appendActimeoOption )
403407 } else {
404- if accountName == "" || accountKey == " " {
405- return nil , status . Errorf ( codes . Internal , "accountName(%s) or accountKey is empty" , accountName )
406- }
407- if runtime . GOOS == "windows" {
408- mountOptions = []string {fmt .Sprintf ("AZURE \\ %s" , accountName )}
409- sensitiveMountOptions = [] string { accountKey }
408+ if mountWithManagedIdentity && runtime . GOOS != "windows " {
409+ if clientID == "" {
410+ clientID = d . cloud . Config . AzureAuthConfig . UserAssignedIdentityID
411+ }
412+ sensitiveMountOptions = []string {"sec=krb5,cruid=0,upcall_target=mount" , fmt .Sprintf ("username= %s" , clientID )}
413+ klog . V ( 2 ). Infof ( "using managed identity %s for volume %s with mount options: %v" , clientID , volumeID , sensitiveMountOptions )
410414 } else {
411- if err := os . MkdirAll ( targetPath , os . FileMode ( mountPermissions )); err != nil {
412- return nil , status .Error (codes .Internal , fmt . Sprintf ( "MkdirAll %s failed with error: %v " , targetPath , err ) )
415+ if accountName == "" || accountKey == "" {
416+ return nil , status .Errorf (codes .Internal , "accountName(%s) or accountKey is empty " , accountName )
413417 }
414- // parameters suggested by https://azure.microsoft.com/en-us/documentation/articles/storage-how-to-use-files-linux/
415- sensitiveMountOptions = []string {fmt .Sprintf ("username=%s,password=%s" , accountName , accountKey )}
418+ if runtime .GOOS == "windows" {
419+ mountOptions = []string {fmt .Sprintf ("AZURE\\ %s" , accountName )}
420+ sensitiveMountOptions = []string {accountKey }
421+ } else {
422+ if err := os .MkdirAll (targetPath , os .FileMode (mountPermissions )); err != nil {
423+ return nil , status .Error (codes .Internal , fmt .Sprintf ("MkdirAll %s failed with error: %v" , targetPath , err ))
424+ }
425+ // parameters suggested by https://azure.microsoft.com/en-us/documentation/articles/storage-how-to-use-files-linux/
426+ sensitiveMountOptions = []string {fmt .Sprintf ("username=%s,password=%s" , accountName , accountKey )}
427+ }
428+ }
429+
430+ if runtime .GOOS != "windows" {
416431 if ephemeralVol {
417432 cifsMountFlags = util .JoinMountOptions (cifsMountFlags , strings .Split (ephemeralVolMountOptions , "," ))
418433 }
@@ -456,6 +471,11 @@ func (d *Driver) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRe
456471 klog .V (2 ).Infof ("mount with proxy succeeded for %s" , cifsMountPath )
457472 } else {
458473 execFunc := func () error {
474+ if mountWithManagedIdentity && protocol != nfs && runtime .GOOS != "windows" {
475+ if out , err := setCredentialCache (server , clientID ); err != nil {
476+ return fmt .Errorf ("setCredentialCache failed for %s with error: %v, output: %s" , server , err , out )
477+ }
478+ }
459479 return SMBMount (d .mounter , source , cifsMountPath , mountFsType , mountOptions , sensitiveMountOptions )
460480 }
461481 timeoutFunc := func () error { return fmt .Errorf ("time out" ) }
0 commit comments