@@ -391,6 +391,7 @@ func (d *NASQtreeStorageDriver) Create(
391391 spaceReserve = collection .GetV (opts , "spaceReserve" , storagePool .InternalAttributes ()[SpaceReserve ])
392392 snapshotPolicy = collection .GetV (opts , "snapshotPolicy" , storagePool .InternalAttributes ()[SnapshotPolicy ])
393393 snapshotReserve = storagePool .InternalAttributes ()[SnapshotReserve ]
394+ adAdminUser = collection .GetV (opts , "adAdminUser" , storagePool .InternalAttributes ()[ADAdminUser ])
394395 snapshotDir = collection .GetV (opts , "snapshotDir" , storagePool .InternalAttributes ()[SnapshotDir ])
395396 encryption = collection .GetV (opts , "encryption" , storagePool .InternalAttributes ()[Encryption ])
396397
@@ -499,7 +500,14 @@ func (d *NASQtreeStorageDriver) Create(
499500 }
500501
501502 if d .Config .NASType == sa .SMB {
502- if err = d .EnsureSMBShare (ctx , flexvol ); err != nil {
503+ if adAdminUser != "" {
504+ if _ , exists := volConfig .SMBShareACL [adAdminUser ]; ! exists {
505+ volConfig .SMBShareACL [adAdminUser ] = ADAdminUserPermission
506+ }
507+ }
508+
509+ shareName , sharePath := getSMBShareNamePath (flexvol , name , volConfig .SecureSMBEnabled )
510+ if err = d .EnsureSMBShare (ctx , shareName , sharePath , volConfig .SMBShareACL , volConfig .SecureSMBEnabled ); err != nil {
503511 return err
504512 }
505513 }
@@ -513,7 +521,7 @@ func (d *NASQtreeStorageDriver) Create(
513521
514522// CreateClone creates a volume clone
515523func (d * NASQtreeStorageDriver ) CreateClone (
516- ctx context.Context , sourceVolConfig , cloneVolConfig * storage.VolumeConfig , _ storage.Pool ,
524+ ctx context.Context , sourceVolConfig , cloneVolConfig * storage.VolumeConfig , storagePool storage.Pool ,
517525) error {
518526 name := cloneVolConfig .InternalName
519527 source := cloneVolConfig .CloneSourceVolumeInternal
@@ -548,6 +556,32 @@ func (d *NASQtreeStorageDriver) CreateClone(
548556 return fmt .Errorf ("snapshot directory access is set to %t and readOnly clone is set to %t " ,
549557 * storageVolume .SnapshotDir , cloneVolConfig .ReadOnlyClone )
550558 }
559+
560+ // If the NAS type is SMB and Secure SMB is enabled, configure SMB share and ACLs for the clone.
561+ if d .Config .NASType == sa .SMB && cloneVolConfig .SecureSMBEnabled {
562+ adAdminUser := d .Config .ADAdminUser
563+
564+ // If a storage pool is set, prefer its AD admin user if available.
565+ if ! storage .IsStoragePoolUnset (storagePool ) {
566+ if spAdminUser := storagePool .InternalAttributes ()[ADAdminUser ]; spAdminUser != "" {
567+ adAdminUser = spAdminUser
568+ }
569+ }
570+
571+ // Add the AD admin user to the SMB share ACL with the necessary permissions if not already present.
572+ if adAdminUser != "" {
573+ if _ , exists := cloneVolConfig .SMBShareACL [adAdminUser ]; ! exists {
574+ cloneVolConfig .SMBShareACL [adAdminUser ] = ADAdminUserPermission
575+ }
576+ }
577+
578+ // Determine the SMB share path to create new SMB Share.
579+ _ , sharePath := getSMBShareNamePath (flexvol , source , cloneVolConfig .SecureSMBEnabled )
580+ if err := d .EnsureSMBShare (ctx , name , sharePath , cloneVolConfig .SMBShareACL ,
581+ cloneVolConfig .SecureSMBEnabled ); err != nil {
582+ return err
583+ }
584+ }
551585 } else {
552586 return fmt .Errorf ("cloning is not supported by backend type %s" , d .Name ())
553587 }
@@ -575,14 +609,19 @@ func (d *NASQtreeStorageDriver) Destroy(ctx context.Context, volConfig *storage.
575609 "name" : name ,
576610 }
577611
578- // If it's a RO clone, no need to delete the volume
579- if volConfig .ReadOnlyClone {
580- return nil
581- }
582-
583612 Logd (ctx , d .Name (), d .Config .DebugTraceFlags ["method" ]).WithFields (fields ).Trace (">>>> Destroy" )
584613 defer Logd (ctx , d .Name (), d .Config .DebugTraceFlags ["method" ]).WithFields (fields ).Trace ("<<<< Destroy" )
585614
615+ // Handle ReadOnlyClone case early
616+ if volConfig .ReadOnlyClone {
617+ if d .Config .NASType == sa .SMB && volConfig .SecureSMBEnabled {
618+ if err := d .DestroySMBShare (ctx , name ); err != nil {
619+ return err
620+ }
621+ }
622+ return nil // Return early for all ReadOnlyClone cases
623+ }
624+
586625 // Ensure the deleted qtree reaping job doesn't interfere with this workflow
587626 locks .Lock (ctx , "destroy" , d .sharedLockID )
588627 defer locks .Unlock (ctx , "destroy" , d .sharedLockID )
@@ -639,6 +678,12 @@ func (d *NASQtreeStorageDriver) Destroy(ctx context.Context, volConfig *storage.
639678 return deleteError
640679 }
641680
681+ if d .Config .NASType == sa .SMB && volConfig .SecureSMBEnabled {
682+ if err := d .DestroySMBShare (ctx , name ); err != nil {
683+ return err
684+ }
685+ }
686+
642687 return nil
643688}
644689
@@ -2542,37 +2587,58 @@ func (d NASQtreeStorageDriver) getQtreesInPool(
25422587}
25432588
25442589// EnsureSMBShare ensures that required SMB share is made available.
2545- func (d * NASQtreeStorageDriver ) EnsureSMBShare (
2546- ctx context.Context , name string ,
2590+ func (d NASQtreeStorageDriver ) EnsureSMBShare (
2591+ ctx context.Context , name , path string , smbShareACL map [ string ] string , secureSMBEnabled bool ,
25472592) error {
2548- if d .Config .SMBShare != "" {
2549- // If user did specify SMB share, and it does not exist, create an SMB share with the specified name.
2550- share , err := d .API .SMBShareExists (ctx , d .Config .SMBShare )
2551- if err != nil {
2593+ shareName := name
2594+ sharePath := path
2595+
2596+ // Determine share name and path based on secureSMBEnabled and configuration
2597+ if ! secureSMBEnabled && d .Config .SMBShare != "" {
2598+ shareName = d .Config .SMBShare
2599+ sharePath = "/"
2600+ }
2601+
2602+ // Check if the share exists
2603+ if shareExists , err := d .API .SMBShareExists (ctx , shareName ); err != nil {
2604+ return err
2605+ } else if ! shareExists {
2606+ // Create the share if it does not exist
2607+ if err = d .API .SMBShareCreate (ctx , shareName , sharePath ); err != nil {
25522608 return err
25532609 }
2610+ }
25542611
2555- // If share is not present create it.
2556- if ! share {
2557- if err := d .API .SMBShareCreate (ctx , d .Config .SMBShare , "/" ); err != nil {
2558- return err
2559- }
2560- }
2561- } else {
2562- // If user did not specify SMB share in backend configuration, create an SMB share with the name passed.
2563- share , err := d .API .SMBShareExists (ctx , name )
2564- if err != nil {
2612+ // If secure SMB is enabled, configure access control
2613+ if secureSMBEnabled {
2614+ // Delete the Everyone Access Control created by default during share creation by ONTAP
2615+ if err := d .API .SMBShareAccessControlDelete (ctx , shareName , smbShareDeleteACL ); err != nil {
25652616 return err
25662617 }
25672618
2568- // If share is not present create it.
2569- if ! share {
2570- if err := d .API .SMBShareCreate (ctx , name , "/" + name ); err != nil {
2571- return err
2572- }
2619+ if err := d .API .SMBShareAccessControlCreate (ctx , shareName , smbShareACL ); err != nil {
2620+ return err
25732621 }
25742622 }
2623+ return nil
2624+ }
25752625
2626+ // DestroySMBShare destroys an SMB share
2627+ func (d NASQtreeStorageDriver ) DestroySMBShare (
2628+ ctx context.Context , name string ,
2629+ ) error {
2630+ // If the share being deleted matches with the backend config, Trident will not delete the SMB share.
2631+ if d .Config .SMBShare == name {
2632+ return nil
2633+ }
2634+
2635+ if shareExists , err := d .API .SMBShareExists (ctx , name ); err != nil {
2636+ return err
2637+ } else if shareExists {
2638+ if err := d .API .SMBShareDestroy (ctx , name ); err != nil {
2639+ return err
2640+ }
2641+ }
25762642 return nil
25772643}
25782644
0 commit comments