2020-08-11 04:38:42 +00:00
|
|
|
package server
|
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/apex/log"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/pterodactyl/wings/config"
|
|
|
|
"github.com/pterodactyl/wings/environment"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
// To avoid confusion when working with mounts, assume that a server.Mount has not been properly
|
|
|
|
// cleaned up and had the paths set. An environment.Mount should only be returned with valid paths
|
|
|
|
// that have been checked.
|
|
|
|
type Mount environment.Mount
|
|
|
|
|
|
|
|
// Returns the default container mounts for the server instance. This includes the data directory
|
|
|
|
// for the server as well as any timezone related files if they exist on the host system so that
|
|
|
|
// servers running within the container will use the correct time.
|
|
|
|
func (s *Server) Mounts() []environment.Mount {
|
|
|
|
var m []environment.Mount
|
|
|
|
|
|
|
|
m = append(m, environment.Mount{
|
|
|
|
Default: true,
|
|
|
|
Target: "/home/container",
|
2020-09-27 19:24:08 +00:00
|
|
|
Source: s.Filesystem().Path(),
|
2020-08-11 04:38:42 +00:00
|
|
|
ReadOnly: false,
|
|
|
|
})
|
|
|
|
|
|
|
|
// Try to mount in /etc/localtime and /etc/timezone if they exist on the host system.
|
|
|
|
if _, err := os.Stat("/etc/localtime"); err != nil {
|
|
|
|
if !os.IsNotExist(err) {
|
|
|
|
log.WithField("error", errors.WithStack(err)).Warn("failed to stat /etc/localtime due to an error")
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
m = append(m, environment.Mount{
|
|
|
|
Target: "/etc/localtime",
|
|
|
|
Source: "/etc/localtime",
|
|
|
|
ReadOnly: true,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := os.Stat("/etc/timezone"); err != nil {
|
|
|
|
if !os.IsNotExist(err) {
|
|
|
|
log.WithField("error", errors.WithStack(err)).Warn("failed to stat /etc/timezone due to an error")
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
m = append(m, environment.Mount{
|
|
|
|
Target: "/etc/timezone",
|
|
|
|
Source: "/etc/timezone",
|
|
|
|
ReadOnly: true,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Also include any of this server's custom mounts when returning them.
|
|
|
|
return append(m, s.customMounts()...)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns the custom mounts for a given server after verifying that they are within a list of
|
|
|
|
// allowed mount points for the node.
|
|
|
|
func (s *Server) customMounts() []environment.Mount {
|
|
|
|
var mounts []environment.Mount
|
|
|
|
|
|
|
|
// TODO: probably need to handle things trying to mount directories that do not exist.
|
|
|
|
for _, m := range s.Config().Mounts {
|
|
|
|
source := filepath.Clean(m.Source)
|
|
|
|
target := filepath.Clean(m.Target)
|
|
|
|
|
|
|
|
logger := s.Log().WithFields(log.Fields{
|
|
|
|
"source_path": source,
|
|
|
|
"target_path": target,
|
|
|
|
"read_only": m.ReadOnly,
|
|
|
|
})
|
|
|
|
|
|
|
|
mounted := false
|
|
|
|
for _, allowed := range config.Get().AllowedMounts {
|
|
|
|
if !strings.HasPrefix(source, allowed) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
mounted = true
|
|
|
|
mounts = append(mounts, environment.Mount{
|
|
|
|
Source: source,
|
|
|
|
Target: target,
|
|
|
|
ReadOnly: m.ReadOnly,
|
|
|
|
})
|
|
|
|
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
if !mounted {
|
|
|
|
logger.Warn("skipping custom server mount, not in list of allowed mount points")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return mounts
|
|
|
|
}
|