@@ -531,6 +531,53 @@ func CreateFedTok(ctx context.Context, server server_structs.XRootDServer) (tok
531531 return
532532}
533533
534+ // getFedTokenTempDir returns the temporary directory for fed token writes
535+ // This func is placed here to avoid circular dependencies.
536+ func getFedTokenTempDir (server server_structs.XRootDServer ) string {
537+ tokLoc := server .GetFedTokLocation ()
538+ tokDir := filepath .Dir (tokLoc )
539+ dir := filepath .Dir (tokDir )
540+ return filepath .Join (dir , "fed-token-temp" )
541+ }
542+
543+ // SetupFedTokDirs creates the permanent and temporary directory for the federation token file
544+ // and sets proper perms. It intends to be called once at server startup. The permanent directory
545+ // is always owned by xrootd user. In normal mode, the temporary directory is owned by the root.
546+ // While in drop privileges mode, it is owned by the pelican user.
547+ func SetupFedTokDirs (server server_structs.XRootDServer ) error {
548+ // Permanent directory
549+ xrootdUid , err := config .GetDaemonUID ()
550+ if err != nil {
551+ return errors .Wrap (err , "failed to get xrootd user" )
552+ }
553+ xrootdGid , err := config .GetDaemonGID ()
554+ if err != nil {
555+ return errors .Wrap (err , "failed to get xrootd group" )
556+ }
557+ permanentDir := filepath .Dir (server .GetFedTokLocation ())
558+ err = config .MkdirAll (permanentDir , 0700 , xrootdUid , xrootdGid )
559+ if err != nil {
560+ return errors .Wrapf (err , "failed to create directory %s" , permanentDir )
561+ }
562+
563+ // Temporary directory
564+ puser , err := config .GetPelicanUser ()
565+ if err != nil {
566+ return errors .Wrap (err , "failed to get pelican user" )
567+ }
568+
569+ tempDir := getFedTokenTempDir (server )
570+ if tempDir == "" {
571+ return errors .New ("the temporary directory for federation token writes is an empty string" )
572+ }
573+
574+ err = config .MkdirAll (tempDir , 0750 , puser .Uid , puser .Gid )
575+ if err != nil {
576+ return errors .Wrapf (err , "failed to create directory %s" , tempDir )
577+ }
578+ return nil
579+ }
580+
534581// FedTokCopyToXrootdFunc is an optional callback used when Server.DropPrivileges is true.
535582// It is defined here so that server_utils does not import the xrootd package; the caller
536583// (e.g. launchers/cache_serve) wires in xrootd.FileCopyToXrootdDir to avoid import cycles.
@@ -543,14 +590,9 @@ func SetFedTok(ctx context.Context, server server_structs.XRootDServer, tok stri
543590 return errors .New ("token location is empty" )
544591 }
545592
546- dir := filepath .Dir (tokLoc )
547- if err := os .MkdirAll (dir , 0755 ); err != nil {
548- return errors .Wrap (err , "failed to create fed token directories" )
549- }
550-
551593 // Create a temporary file for storing the token. Later we'll do an atomic rename
552594 filenamePattern := fmt .Sprintf (".fedtoken.%d.*" , time .Now ().UnixNano ())
553- tmpFile , err := os .CreateTemp (dir , filenamePattern )
595+ tmpFile , err := os .CreateTemp (getFedTokenTempDir ( server ) , filenamePattern )
554596 if err != nil {
555597 return errors .Wrap (err , "failed to create temporary token file" )
556598 }
@@ -561,49 +603,41 @@ func SetFedTok(ctx context.Context, server server_structs.XRootDServer, tok stri
561603 os .Remove (tmpName )
562604 }()
563605
564- // Change ownership to xrootd user
565- uid , err := config .GetDaemonUID ()
566- if err != nil {
567- return errors .Wrap (err , "failed to get daemon UID" )
568- }
569- gid , err := config .GetDaemonGID ()
570- if err != nil {
571- return errors .Wrap (err , "failed to get daemon GID" )
572- }
573-
574- if err := os .Chown (tmpName , uid , gid ); err != nil {
575- return errors .Wrapf (err , "failed to change token file ownership of %s to %d:%d" , tmpName , uid , gid )
576- }
577-
578606 if _ , err := tmpFile .WriteString (tok ); err != nil {
579607 return errors .Wrap (err , "failed to write token to temporary file" )
580608 }
581609
582- if param .Server_DropPrivileges .GetBool () && copyToXrootdDir != nil {
610+ if ! param .Server_DropPrivileges .GetBool () {
611+ // Change ownership to xrootd user
612+ uid , err := config .GetDaemonUID ()
613+ if err != nil {
614+ return errors .Wrap (err , "failed to get daemon UID" )
615+ }
616+ gid , err := config .GetDaemonGID ()
617+ if err != nil {
618+ return errors .Wrap (err , "failed to get daemon GID" )
619+ }
620+
621+ if err := os .Chown (tmpName , uid , gid ); err != nil {
622+ return errors .Wrapf (err , "failed to change token file ownership of %s to %d:%d" , tmpName , uid , gid )
623+ }
624+
625+ if err := tmpFile .Sync (); err != nil {
626+ return errors .Wrap (err , "failed to sync token file" )
627+ }
628+
629+ if err := os .Rename (tmpName , tokLoc ); err != nil {
630+ return errors .Wrap (err , "failed to move token file to final location" )
631+ }
632+ } else if param .Server_DropPrivileges .GetBool () && copyToXrootdDir != nil {
583633 // After writing the token content to the file, the file pointer remains at the end.
584634 // Seek back to the beginning so the copy operation reads from the start.
585635 if _ , err := tmpFile .Seek (0 , io .SeekStart ); err != nil {
586636 return errors .Wrap (err , "failed to seek to beginning of the file" )
587637 }
588638 if err := copyToXrootdDir (tmpFile ); err != nil {
589- return errors .Wrapf (err , "failed to copy token file to xrootd directory" )
590- }
591- if err := tmpFile .Close (); err != nil {
592- return errors .Wrap (err , "failed to close temporary token file" )
639+ return errors .Wrapf (err , "failed to rename the federation token file via the xrdhttp-pelican plugin" )
593640 }
594- return nil
595- }
596-
597- if err := tmpFile .Sync (); err != nil {
598- return errors .Wrap (err , "failed to sync token file" )
599- }
600-
601- if err := tmpFile .Close (); err != nil {
602- return errors .Wrap (err , "failed to close temporary token file" )
603- }
604-
605- if err := os .Rename (tmpName , tokLoc ); err != nil {
606- return errors .Wrap (err , "failed to move token file to final location" )
607641 }
608642
609643 return nil
0 commit comments