Code maintenance: OS package for file system
- OS custom internal package for file system interaction - Remove fileManager external dependency - Closer API to Go's native API on the OS - Create directories at startup - Better testability - Move Unsetenv to os interface
This commit is contained in:
@@ -1,31 +1,68 @@
|
||||
package openvpn
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/qdm12/gluetun/internal/constants"
|
||||
"github.com/qdm12/golibs/files"
|
||||
)
|
||||
|
||||
// WriteAuthFile writes the OpenVPN auth file to disk with the right permissions.
|
||||
func (c *configurator) WriteAuthFile(user, password string, uid, gid int) error {
|
||||
exists, err := c.fileManager.FileExists(string(constants.OpenVPNAuthConf))
|
||||
if err != nil {
|
||||
const filepath = string(constants.OpenVPNAuthConf)
|
||||
file, err := c.os.OpenFile(filepath, os.O_RDONLY, 0)
|
||||
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
} else if exists {
|
||||
data, err := c.fileManager.ReadFile(string(constants.OpenVPNAuthConf))
|
||||
}
|
||||
|
||||
if os.IsNotExist(err) {
|
||||
file, err = c.os.OpenFile(filepath, os.O_WRONLY|os.O_CREATE, 0400)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
lines := strings.Split(string(data), "\n")
|
||||
if len(lines) > 1 && lines[0] == user && lines[1] == password {
|
||||
return nil
|
||||
_, err = file.WriteString(user + "\n" + password)
|
||||
if err != nil {
|
||||
_ = file.Close()
|
||||
return err
|
||||
}
|
||||
c.logger.Info("username and password changed", constants.OpenVPNAuthConf)
|
||||
err = file.Chown(uid, gid)
|
||||
if err != nil {
|
||||
_ = file.Close()
|
||||
return err
|
||||
}
|
||||
return file.Close()
|
||||
}
|
||||
return c.fileManager.WriteLinesToFile(
|
||||
string(constants.OpenVPNAuthConf),
|
||||
[]string{user, password},
|
||||
files.Ownership(uid, gid),
|
||||
files.Permissions(constants.UserReadPermission))
|
||||
|
||||
data, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
_ = file.Close()
|
||||
return err
|
||||
}
|
||||
if err := file.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
lines := strings.Split(string(data), "\n")
|
||||
if len(lines) > 1 && lines[0] == user && lines[1] == password {
|
||||
return nil
|
||||
}
|
||||
|
||||
c.logger.Info("username and password changed in %s", constants.OpenVPNAuthConf)
|
||||
file, err = c.os.OpenFile(filepath, os.O_TRUNC|os.O_WRONLY, 0400)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = file.WriteString(user + "\n" + password)
|
||||
if err != nil {
|
||||
_ = file.Close()
|
||||
return err
|
||||
}
|
||||
err = file.Chown(uid, gid)
|
||||
if err != nil {
|
||||
_ = file.Close()
|
||||
return err
|
||||
}
|
||||
return file.Close()
|
||||
}
|
||||
|
||||
@@ -4,17 +4,18 @@ import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/qdm12/gluetun/internal/constants"
|
||||
"github.com/qdm12/gluetun/internal/firewall"
|
||||
"github.com/qdm12/gluetun/internal/models"
|
||||
"github.com/qdm12/gluetun/internal/os"
|
||||
"github.com/qdm12/gluetun/internal/provider"
|
||||
"github.com/qdm12/gluetun/internal/routing"
|
||||
"github.com/qdm12/gluetun/internal/settings"
|
||||
"github.com/qdm12/golibs/command"
|
||||
"github.com/qdm12/golibs/files"
|
||||
"github.com/qdm12/golibs/logging"
|
||||
)
|
||||
|
||||
@@ -43,7 +44,7 @@ type looper struct {
|
||||
// Other objects
|
||||
logger, pfLogger logging.Logger
|
||||
client *http.Client
|
||||
fileManager files.FileManager
|
||||
openFile os.OpenFileFunc
|
||||
streamMerger command.StreamMerger
|
||||
cancel context.CancelFunc
|
||||
// Internal channels and locks
|
||||
@@ -57,7 +58,7 @@ type looper struct {
|
||||
func NewLooper(settings settings.OpenVPN,
|
||||
username string, uid, gid int, allServers models.AllServers,
|
||||
conf Configurator, fw firewall.Configurator, routing routing.Routing,
|
||||
logger logging.Logger, client *http.Client, fileManager files.FileManager,
|
||||
logger logging.Logger, client *http.Client, openFile os.OpenFileFunc,
|
||||
streamMerger command.StreamMerger, cancel context.CancelFunc) Looper {
|
||||
return &looper{
|
||||
state: state{
|
||||
@@ -74,7 +75,7 @@ func NewLooper(settings settings.OpenVPN,
|
||||
logger: logger.WithPrefix("openvpn: "),
|
||||
pfLogger: logger.WithPrefix("port forwarding: "),
|
||||
client: client,
|
||||
fileManager: fileManager,
|
||||
openFile: openFile,
|
||||
streamMerger: streamMerger,
|
||||
cancel: cancel,
|
||||
start: make(chan struct{}),
|
||||
@@ -115,8 +116,8 @@ func (l *looper) Run(ctx context.Context, wg *sync.WaitGroup) {
|
||||
settings.Auth,
|
||||
settings.Provider.ExtraConfigOptions,
|
||||
)
|
||||
if err := l.fileManager.WriteLinesToFile(string(constants.OpenVPNConf), lines,
|
||||
files.Ownership(l.uid, l.gid), files.Permissions(constants.UserReadPermission)); err != nil {
|
||||
|
||||
if err := writeOpenvpnConf(lines, l.openFile); err != nil {
|
||||
l.logger.Error(err)
|
||||
l.cancel()
|
||||
return
|
||||
@@ -239,6 +240,22 @@ func (l *looper) portForward(ctx context.Context, wg *sync.WaitGroup,
|
||||
return settings.Provider.PortForwarding.Filepath
|
||||
}
|
||||
providerConf.PortForward(ctx,
|
||||
client, l.fileManager, l.pfLogger,
|
||||
client, l.openFile, l.pfLogger,
|
||||
gateway, l.fw, syncState)
|
||||
}
|
||||
|
||||
func writeOpenvpnConf(lines []string, openFile os.OpenFileFunc) error {
|
||||
const filepath = string(constants.OpenVPNConf)
|
||||
file, err := openFile(filepath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = file.WriteString(strings.Join(lines, "\n"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := file.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,10 +3,9 @@ package openvpn
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/qdm12/gluetun/internal/os"
|
||||
"github.com/qdm12/golibs/command"
|
||||
"github.com/qdm12/golibs/files"
|
||||
"github.com/qdm12/golibs/logging"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
@@ -20,21 +19,19 @@ type Configurator interface {
|
||||
}
|
||||
|
||||
type configurator struct {
|
||||
fileManager files.FileManager
|
||||
logger logging.Logger
|
||||
commander command.Commander
|
||||
openFile func(name string, flag int, perm os.FileMode) (*os.File, error)
|
||||
mkDev func(major uint32, minor uint32) uint64
|
||||
mkNod func(path string, mode uint32, dev int) error
|
||||
logger logging.Logger
|
||||
commander command.Commander
|
||||
os os.OS
|
||||
mkDev func(major uint32, minor uint32) uint64
|
||||
mkNod func(path string, mode uint32, dev int) error
|
||||
}
|
||||
|
||||
func NewConfigurator(logger logging.Logger, fileManager files.FileManager) Configurator {
|
||||
func NewConfigurator(logger logging.Logger, os os.OS) Configurator {
|
||||
return &configurator{
|
||||
fileManager: fileManager,
|
||||
logger: logger.WithPrefix("openvpn configurator: "),
|
||||
commander: command.NewCommander(),
|
||||
openFile: os.OpenFile,
|
||||
mkDev: unix.Mkdev,
|
||||
mkNod: unix.Mknod,
|
||||
logger: logger.WithPrefix("openvpn configurator: "),
|
||||
commander: command.NewCommander(),
|
||||
os: os,
|
||||
mkDev: unix.Mkdev,
|
||||
mkNod: unix.Mknod,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
// CheckTUN checks the tunnel device is present and accessible.
|
||||
func (c *configurator) CheckTUN() error {
|
||||
c.logger.Info("checking for device %s", constants.TunnelDevice)
|
||||
f, err := c.openFile(string(constants.TunnelDevice), os.O_RDWR, 0)
|
||||
f, err := c.os.OpenFile(string(constants.TunnelDevice), os.O_RDWR, 0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("TUN device is not available: %w", err)
|
||||
}
|
||||
@@ -23,9 +23,10 @@ func (c *configurator) CheckTUN() error {
|
||||
|
||||
func (c *configurator) CreateTUN() error {
|
||||
c.logger.Info("creating %s", constants.TunnelDevice)
|
||||
if err := c.fileManager.CreateDir("/dev/net"); err != nil {
|
||||
if err := c.os.MkdirAll("/dev/net", 0751); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
const (
|
||||
major = 10
|
||||
minor = 200
|
||||
@@ -34,8 +35,17 @@ func (c *configurator) CreateTUN() error {
|
||||
if err := c.mkNod(string(constants.TunnelDevice), unix.S_IFCHR, int(dev)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := c.fileManager.SetUserPermissions(string(constants.TunnelDevice), 0666); err != nil {
|
||||
|
||||
const filepath = string(constants.TunnelDevice)
|
||||
file, err := c.os.OpenFile(filepath, os.O_WRONLY, 0666)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
const readWriteAllPerms os.FileMode = 0666
|
||||
if err := file.Chmod(readWriteAllPerms); err != nil {
|
||||
_ = file.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
return file.Close()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user