diff --git a/lib/config/fileconf.go b/lib/config/fileconf.go index e087351fb0c1a..5c2b719fa3c3d 100644 --- a/lib/config/fileconf.go +++ b/lib/config/fileconf.go @@ -20,8 +20,10 @@ import ( "bytes" "crypto/tls" "encoding/base64" + "errors" "fmt" "io" + "io/fs" "net" "net/url" "os" @@ -91,7 +93,10 @@ type FileConfig struct { func ReadFromFile(filePath string) (*FileConfig, error) { f, err := os.Open(filePath) if err != nil { - return nil, trace.Wrap(err, fmt.Sprintf("failed to open file: %v", filePath)) + if errors.Is(err, fs.ErrPermission) { + return nil, trace.Wrap(err, "failed to open file for Teleport configuration: %v. Ensure that you are running as a user with appropriate permissions.", filePath) + } + return nil, trace.Wrap(err, "failed to open file for Teleport configuration at %v", filePath) } defer f.Close() return ReadConfig(f) diff --git a/lib/service/service.go b/lib/service/service.go index 75ac2dc52d58e..441aa6d81e105 100644 --- a/lib/service/service.go +++ b/lib/service/service.go @@ -24,8 +24,10 @@ import ( "crypto/tls" "crypto/x509" "encoding/hex" + "errors" "fmt" "io" + "io/fs" "net" "net/http" "net/http/httptest" @@ -626,6 +628,9 @@ func NewTeleport(cfg *Config) (*TeleportProcess, error) { if os.IsNotExist(err) { err := os.MkdirAll(cfg.DataDir, os.ModeDir|0700) if err != nil { + if errors.Is(err, fs.ErrPermission) { + cfg.Log.Errorf("Teleport does not have permission to write to: %v. Ensure that you are running as a user with appropriate permissions.", cfg.DataDir) + } return nil, trace.ConvertSystemError(err) } } @@ -642,6 +647,9 @@ func NewTeleport(cfg *Config) (*TeleportProcess, error) { cfg.HostUUID, err = utils.ReadHostUUID(cfg.DataDir) if err != nil { if !trace.IsNotFound(err) { + if errors.Is(err, fs.ErrPermission) { + cfg.Log.Errorf("Teleport does not have permission to write to: %v. Ensure that you are running as a user with appropriate permissions.", cfg.DataDir) + } return nil, trace.Wrap(err) } if len(cfg.Identities) != 0 { @@ -662,6 +670,9 @@ func NewTeleport(cfg *Config) (*TeleportProcess, error) { cfg.Log.Infof("Generating new host UUID: %v.", cfg.HostUUID) } if err := utils.WriteHostUUID(cfg.DataDir, cfg.HostUUID); err != nil { + if errors.Is(err, fs.ErrPermission) { + cfg.Log.Errorf("Teleport does not have permission to write to: %v. Ensure that you are running as a user with appropriate permissions.", cfg.DataDir) + } return nil, trace.Wrap(err) } } diff --git a/lib/utils/utils.go b/lib/utils/utils.go index 96893ee62935e..c0ebd7c13d967 100644 --- a/lib/utils/utils.go +++ b/lib/utils/utils.go @@ -18,8 +18,10 @@ package utils import ( "context" + "errors" "fmt" "io" + "io/fs" "net" "net/url" "os" @@ -320,10 +322,18 @@ func ReadPath(path string) ([]byte, error) { } abs, err := filepath.EvalSymlinks(s) if err != nil { + if errors.Is(err, fs.ErrPermission) { + //do not convert to system error as this loses the ability to compare that it is a permission error + return nil, err + } return nil, trace.ConvertSystemError(err) } bytes, err := os.ReadFile(abs) if err != nil { + if errors.Is(err, fs.ErrPermission) { + //do not convert to system error as this loses the ability to compare that it is a permission error + return nil, err + } return nil, trace.ConvertSystemError(err) } return bytes, nil @@ -429,6 +439,10 @@ func GetFreeTCPPorts(n int, offset ...int) (PortList, error) { func ReadHostUUID(dataDir string) (string, error) { out, err := ReadPath(filepath.Join(dataDir, HostUUIDFile)) if err != nil { + if errors.Is(err, fs.ErrPermission) { + //do not convert to system error as this loses the ability to compare that it is a permission error + return "", err + } return "", trace.Wrap(err) } return strings.TrimSpace(string(out)), nil @@ -438,6 +452,10 @@ func ReadHostUUID(dataDir string) (string, error) { func WriteHostUUID(dataDir string, id string) error { err := os.WriteFile(filepath.Join(dataDir, HostUUIDFile), []byte(id), os.ModeExclusive|0400) if err != nil { + if errors.Is(err, fs.ErrPermission) { + //do not convert to system error as this loses the ability to compare that it is a permission error + return err + } return trace.ConvertSystemError(err) } return nil