mirror of
https://github.com/safing/portmaster
synced 2025-04-08 21:19:10 +00:00
commit
f021ec2444
46 changed files with 838 additions and 183 deletions
.gitignoreEarthfile
base
config
database
dataroot
info
updater
utils
cmds
go.modgo.sumservice
core/base
intel/filterlists
mgr
netquery
profile
resolver
ui
updates
spn/testing
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -12,8 +12,7 @@ go.mod.*
|
|||
vendor
|
||||
|
||||
# testing
|
||||
testing
|
||||
spn/testing/simple/testdata
|
||||
testdata
|
||||
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.a
|
||||
|
|
|
@ -70,6 +70,11 @@ build:
|
|||
# ./dist/all/assets.zip
|
||||
BUILD +assets
|
||||
|
||||
build-spn:
|
||||
BUILD +go-build --CMDS="hub" --GOOS="linux" --GOARCH="amd64"
|
||||
BUILD +go-build --CMDS="hub" --GOOS="linux" --GOARCH="arm64"
|
||||
# TODO: Add other platforms
|
||||
|
||||
go-ci:
|
||||
BUILD +go-build --GOOS="linux" --GOARCH="amd64"
|
||||
BUILD +go-build --GOOS="linux" --GOARCH="arm64"
|
||||
|
|
|
@ -144,9 +144,9 @@ func InitializeUnitTestDataroot(testName string) (string, error) {
|
|||
return "", fmt.Errorf("failed to make tmp dir: %w", err)
|
||||
}
|
||||
|
||||
ds := utils.NewDirStructure(basePath, 0o0755)
|
||||
ds := utils.NewDirStructure(basePath, utils.PublicReadPermission)
|
||||
SetDataRoot(ds)
|
||||
err = dataroot.Initialize(basePath, 0o0755)
|
||||
err = dataroot.Initialize(basePath, utils.PublicReadPermission)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to initialize dataroot: %w", err)
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ var (
|
|||
|
||||
// InitializeWithPath initializes the database at the specified location using a path.
|
||||
func InitializeWithPath(dirPath string) error {
|
||||
return Initialize(utils.NewDirStructure(dirPath, 0o0755))
|
||||
return Initialize(utils.NewDirStructure(dirPath, utils.PublicReadPermission))
|
||||
}
|
||||
|
||||
// Initialize initializes the database at the specified location using a dir structure.
|
||||
|
@ -34,7 +34,7 @@ func Initialize(dirStructureRoot *utils.DirStructure) error {
|
|||
rootStructure = dirStructureRoot
|
||||
|
||||
// ensure root and databases dirs
|
||||
databasesStructure = rootStructure.ChildDir(databasesSubDir, 0o0700)
|
||||
databasesStructure = rootStructure.ChildDir(databasesSubDir, utils.AdminOnlyPermission)
|
||||
err := databasesStructure.Ensure()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not create/open database directory (%s): %w", rootStructure.Path, err)
|
||||
|
@ -67,7 +67,7 @@ func Shutdown() (err error) {
|
|||
|
||||
// getLocation returns the storage location for the given name and type.
|
||||
func getLocation(name, storageType string) (string, error) {
|
||||
location := databasesStructure.ChildDir(name, 0o0700).ChildDir(storageType, 0o0700)
|
||||
location := databasesStructure.ChildDir(name, utils.AdminOnlyPermission).ChildDir(storageType, utils.AdminOnlyPermission)
|
||||
// check location
|
||||
err := location.Ensure()
|
||||
if err != nil {
|
||||
|
|
|
@ -15,7 +15,6 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hectane/go-acl"
|
||||
"github.com/safing/portmaster/base/database/iterator"
|
||||
"github.com/safing/portmaster/base/database/query"
|
||||
"github.com/safing/portmaster/base/database/record"
|
||||
|
@ -289,11 +288,8 @@ func writeFile(filename string, data []byte, perm os.FileMode) error {
|
|||
defer t.Cleanup() //nolint:errcheck
|
||||
|
||||
// Set permissions before writing data, in case the data is sensitive.
|
||||
if onWindows {
|
||||
err = acl.Chmod(filename, perm)
|
||||
} else {
|
||||
err = t.Chmod(perm)
|
||||
}
|
||||
// TODO(vladimir): to set permissions on windows we need the full path of the file.
|
||||
err = t.Chmod(perm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package dataroot
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
|
||||
"github.com/safing/portmaster/base/utils"
|
||||
)
|
||||
|
@ -10,7 +9,7 @@ import (
|
|||
var root *utils.DirStructure
|
||||
|
||||
// Initialize initializes the data root directory.
|
||||
func Initialize(rootDir string, perm os.FileMode) error {
|
||||
func Initialize(rootDir string, perm utils.FSPermission) error {
|
||||
if root != nil {
|
||||
return errors.New("already initialized")
|
||||
}
|
||||
|
|
|
@ -74,6 +74,7 @@ func Set(setName string, setVersion string, setLicenseName string) {
|
|||
|
||||
if setVersion != "" {
|
||||
version = setVersion
|
||||
versionNumber = setVersion
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,10 +14,10 @@ import (
|
|||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/hectane/go-acl"
|
||||
"github.com/safing/jess/filesig"
|
||||
"github.com/safing/jess/lhash"
|
||||
"github.com/safing/portmaster/base/log"
|
||||
"github.com/safing/portmaster/base/utils"
|
||||
"github.com/safing/portmaster/base/utils/renameio"
|
||||
)
|
||||
|
||||
|
@ -137,17 +137,10 @@ func (reg *ResourceRegistry) fetchFile(ctx context.Context, client *http.Client,
|
|||
return fmt.Errorf("%s: failed to finalize file %s: %w", reg.Name, rv.storagePath(), err)
|
||||
}
|
||||
// set permissions
|
||||
if onWindows {
|
||||
err = acl.Chmod(rv.storagePath(), 0o0755)
|
||||
if err != nil {
|
||||
log.Warningf("%s: failed to set permissions on downloaded file %s: %s", reg.Name, rv.storagePath(), err)
|
||||
}
|
||||
} else {
|
||||
// TODO: only set executable files to 0755, set other to 0644
|
||||
err = os.Chmod(rv.storagePath(), 0o0755) //nolint:gosec // See TODO above.
|
||||
if err != nil {
|
||||
log.Warningf("%s: failed to set permissions on downloaded file %s: %s", reg.Name, rv.storagePath(), err)
|
||||
}
|
||||
// TODO: distinguish between executable and non executable files.
|
||||
err = utils.SetExecPermission(rv.storagePath(), utils.PublicReadPermission)
|
||||
if err != nil {
|
||||
log.Warningf("%s: failed to set permissions on downloaded file %s: %s", reg.Name, rv.storagePath(), err)
|
||||
}
|
||||
|
||||
log.Debugf("%s: fetched %s and stored to %s", reg.Name, downloadURL, rv.storagePath())
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
|
@ -13,10 +12,6 @@ import (
|
|||
"github.com/safing/portmaster/base/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
onWindows = runtime.GOOS == "windows"
|
||||
)
|
||||
|
||||
// ResourceRegistry is a registry for managing update resources.
|
||||
type ResourceRegistry struct {
|
||||
sync.RWMutex
|
||||
|
@ -98,7 +93,7 @@ func (reg *ResourceRegistry) Initialize(storageDir *utils.DirStructure) error {
|
|||
|
||||
// initialize private attributes
|
||||
reg.storageDir = storageDir
|
||||
reg.tmpDir = storageDir.ChildDir("tmp", 0o0700)
|
||||
reg.tmpDir = storageDir.ChildDir("tmp", utils.AdminOnlyPermission)
|
||||
reg.resources = make(map[string]*Resource)
|
||||
if reg.state == nil {
|
||||
reg.state = &RegistryState{}
|
||||
|
|
|
@ -20,7 +20,7 @@ func TestMain(m *testing.M) {
|
|||
DevMode: true,
|
||||
Online: true,
|
||||
}
|
||||
err = registry.Initialize(utils.NewDirStructure(tmpDir, 0o0777))
|
||||
err = registry.Initialize(utils.NewDirStructure(tmpDir, utils.PublicWritePermission))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
|
@ -6,15 +6,13 @@ import (
|
|||
"io/fs"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"github.com/hectane/go-acl"
|
||||
)
|
||||
|
||||
const isWindows = runtime.GOOS == "windows"
|
||||
|
||||
// EnsureDirectory ensures that the given directory exists and that is has the given permissions set.
|
||||
// If path is a file, it is deleted and a directory created.
|
||||
func EnsureDirectory(path string, perm os.FileMode) error {
|
||||
func EnsureDirectory(path string, perm FSPermission) error {
|
||||
// open path
|
||||
f, err := os.Stat(path)
|
||||
if err == nil {
|
||||
|
@ -23,10 +21,10 @@ func EnsureDirectory(path string, perm os.FileMode) error {
|
|||
// directory exists, check permissions
|
||||
if isWindows {
|
||||
// Ignore windows permission error. For none admin users it will always fail.
|
||||
acl.Chmod(path, perm)
|
||||
_ = SetDirPermission(path, perm)
|
||||
return nil
|
||||
} else if f.Mode().Perm() != perm {
|
||||
return os.Chmod(path, perm)
|
||||
} else if f.Mode().Perm() != perm.AsUnixDirExecPermission() {
|
||||
return SetDirPermission(path, perm)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -37,17 +35,17 @@ func EnsureDirectory(path string, perm os.FileMode) error {
|
|||
}
|
||||
// file does not exist (or has been deleted)
|
||||
if err == nil || errors.Is(err, fs.ErrNotExist) {
|
||||
err = os.Mkdir(path, perm)
|
||||
err = os.Mkdir(path, perm.AsUnixDirExecPermission())
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not create dir %s: %w", path, err)
|
||||
}
|
||||
if isWindows {
|
||||
// Ignore windows permission error. For none admin users it will always fail.
|
||||
acl.Chmod(path, perm)
|
||||
return nil
|
||||
} else {
|
||||
return os.Chmod(path, perm)
|
||||
// Set permissions.
|
||||
err = SetDirPermission(path, perm)
|
||||
// Ignore windows permission error. For none admin users it will always fail.
|
||||
if !isWindows {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// other error opening path
|
||||
return fmt.Errorf("failed to access %s: %w", path, err)
|
||||
|
|
20
base/utils/permissions.go
Normal file
20
base/utils/permissions.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
//go:build !windows
|
||||
|
||||
package utils
|
||||
|
||||
import "os"
|
||||
|
||||
// SetDirPermission sets the permission of a directory.
|
||||
func SetDirPermission(path string, perm FSPermission) error {
|
||||
return os.Chmod(path, perm.AsUnixDirExecPermission())
|
||||
}
|
||||
|
||||
// SetExecPermission sets the permission of an executable file.
|
||||
func SetExecPermission(path string, perm FSPermission) error {
|
||||
return SetDirPermission(path, perm)
|
||||
}
|
||||
|
||||
// SetFilePermission sets the permission of a non executable file.
|
||||
func SetFilePermission(path string, perm FSPermission) error {
|
||||
return os.Chmod(path, perm.AsUnixFilePermission())
|
||||
}
|
79
base/utils/permissions_windows.go
Normal file
79
base/utils/permissions_windows.go
Normal file
|
@ -0,0 +1,79 @@
|
|||
//go:build windows
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"github.com/hectane/go-acl"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var (
|
||||
systemSID *windows.SID
|
||||
adminsSID *windows.SID
|
||||
usersSID *windows.SID
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Initialize Security ID for all need groups.
|
||||
// Reference: https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/understand-security-identifiers
|
||||
var err error
|
||||
systemSID, err = windows.StringToSid("S-1-5-18") // SYSTEM (Local System)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
adminsSID, err = windows.StringToSid("S-1-5-32-544") // Administrators
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
usersSID, err = windows.StringToSid("S-1-5-32-545") // Users
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// SetDirPermission sets the permission of a directory.
|
||||
func SetDirPermission(path string, perm FSPermission) error {
|
||||
SetFilePermission(path, perm)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetExecPermission sets the permission of an executable file.
|
||||
func SetExecPermission(path string, perm FSPermission) error {
|
||||
SetFilePermission(path, perm)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetFilePermission sets the permission of a non executable file.
|
||||
func SetFilePermission(path string, perm FSPermission) {
|
||||
switch perm {
|
||||
case AdminOnlyPermission:
|
||||
// Set only admin rights, remove all others.
|
||||
acl.Apply(
|
||||
path,
|
||||
true,
|
||||
false,
|
||||
acl.GrantSid(windows.GENERIC_ALL|windows.STANDARD_RIGHTS_ALL, systemSID),
|
||||
acl.GrantSid(windows.GENERIC_ALL|windows.STANDARD_RIGHTS_ALL, adminsSID),
|
||||
)
|
||||
case PublicReadPermission:
|
||||
// Set admin rights and read/execute rights for users, remove all others.
|
||||
acl.Apply(
|
||||
path,
|
||||
true,
|
||||
false,
|
||||
acl.GrantSid(windows.GENERIC_ALL|windows.STANDARD_RIGHTS_ALL, systemSID),
|
||||
acl.GrantSid(windows.GENERIC_ALL|windows.STANDARD_RIGHTS_ALL, adminsSID),
|
||||
acl.GrantSid(windows.GENERIC_READ|windows.GENERIC_EXECUTE, usersSID),
|
||||
)
|
||||
case PublicWritePermission:
|
||||
// Set full control to admin and regular users. Guest users will not have access.
|
||||
acl.Apply(
|
||||
path,
|
||||
true,
|
||||
false,
|
||||
acl.GrantSid(windows.GENERIC_ALL|windows.STANDARD_RIGHTS_ALL, systemSID),
|
||||
acl.GrantSid(windows.GENERIC_ALL|windows.STANDARD_RIGHTS_ALL, adminsSID),
|
||||
acl.GrantSid(windows.GENERIC_ALL|windows.STANDARD_RIGHTS_ALL, usersSID),
|
||||
)
|
||||
}
|
||||
}
|
|
@ -2,25 +2,61 @@ package utils
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"io/fs"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type FSPermission uint8
|
||||
|
||||
const (
|
||||
AdminOnlyPermission FSPermission = iota
|
||||
PublicReadPermission
|
||||
PublicWritePermission
|
||||
)
|
||||
|
||||
// AsUnixDirExecPermission return the corresponding unix permission for a directory or executable.
|
||||
func (perm FSPermission) AsUnixDirExecPermission() fs.FileMode {
|
||||
switch perm {
|
||||
case AdminOnlyPermission:
|
||||
return 0o700
|
||||
case PublicReadPermission:
|
||||
return 0o755
|
||||
case PublicWritePermission:
|
||||
return 0o777
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// AsUnixFilePermission return the corresponding unix permission for a regular file.
|
||||
func (perm FSPermission) AsUnixFilePermission() fs.FileMode {
|
||||
switch perm {
|
||||
case AdminOnlyPermission:
|
||||
return 0o600
|
||||
case PublicReadPermission:
|
||||
return 0o644
|
||||
case PublicWritePermission:
|
||||
return 0o666
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// DirStructure represents a directory structure with permissions that should be enforced.
|
||||
type DirStructure struct {
|
||||
sync.Mutex
|
||||
|
||||
Path string
|
||||
Dir string
|
||||
Perm os.FileMode
|
||||
Perm FSPermission
|
||||
Parent *DirStructure
|
||||
Children map[string]*DirStructure
|
||||
}
|
||||
|
||||
// NewDirStructure returns a new DirStructure.
|
||||
func NewDirStructure(path string, perm os.FileMode) *DirStructure {
|
||||
func NewDirStructure(path string, perm FSPermission) *DirStructure {
|
||||
return &DirStructure{
|
||||
Path: path,
|
||||
Perm: perm,
|
||||
|
@ -29,7 +65,7 @@ func NewDirStructure(path string, perm os.FileMode) *DirStructure {
|
|||
}
|
||||
|
||||
// ChildDir adds a new child DirStructure and returns it. Should the child already exist, the existing child is returned and the permissions are updated.
|
||||
func (ds *DirStructure) ChildDir(dirName string, perm os.FileMode) (child *DirStructure) {
|
||||
func (ds *DirStructure) ChildDir(dirName string, perm FSPermission) (child *DirStructure) {
|
||||
ds.Lock()
|
||||
defer ds.Unlock()
|
||||
|
||||
|
|
|
@ -13,13 +13,13 @@ func ExampleDirStructure() {
|
|||
// output:
|
||||
// / [755]
|
||||
// /repo [777]
|
||||
// /repo/b [707]
|
||||
// /repo/b/c [750]
|
||||
// /repo/b/d [707]
|
||||
// /repo/b/d/e [707]
|
||||
// /repo/b/d/f [707]
|
||||
// /repo/b/d/f/g [707]
|
||||
// /repo/b/d/f/g/h [707]
|
||||
// /repo/b [755]
|
||||
// /repo/b/c [777]
|
||||
// /repo/b/d [755]
|
||||
// /repo/b/d/e [755]
|
||||
// /repo/b/d/f [755]
|
||||
// /repo/b/d/f/g [755]
|
||||
// /repo/b/d/f/g/h [755]
|
||||
// /secret [700]
|
||||
|
||||
basePath, err := os.MkdirTemp("", "")
|
||||
|
@ -28,12 +28,12 @@ func ExampleDirStructure() {
|
|||
return
|
||||
}
|
||||
|
||||
ds := NewDirStructure(basePath, 0o0755)
|
||||
secret := ds.ChildDir("secret", 0o0700)
|
||||
repo := ds.ChildDir("repo", 0o0777)
|
||||
_ = repo.ChildDir("a", 0o0700)
|
||||
b := repo.ChildDir("b", 0o0707)
|
||||
c := b.ChildDir("c", 0o0750)
|
||||
ds := NewDirStructure(basePath, PublicReadPermission)
|
||||
secret := ds.ChildDir("secret", AdminOnlyPermission)
|
||||
repo := ds.ChildDir("repo", PublicWritePermission)
|
||||
_ = repo.ChildDir("a", AdminOnlyPermission)
|
||||
b := repo.ChildDir("b", PublicReadPermission)
|
||||
c := b.ChildDir("c", PublicWritePermission)
|
||||
|
||||
err = ds.Ensure()
|
||||
if err != nil {
|
||||
|
|
|
@ -33,7 +33,7 @@ func main() {
|
|||
flag.Parse()
|
||||
|
||||
// Set name and license.
|
||||
info.Set("SPN Hub", "", "GPLv3")
|
||||
info.Set("SPN Hub", "0.7.8", "GPLv3")
|
||||
|
||||
// Configure metrics.
|
||||
_ = metrics.SetNamespace("hub")
|
||||
|
@ -45,10 +45,6 @@ func main() {
|
|||
// Set SPN public hub mode.
|
||||
conf.EnablePublicHub(true)
|
||||
|
||||
// Set default log level.
|
||||
log.SetLogLevel(log.WarningLevel)
|
||||
_ = log.Start()
|
||||
|
||||
// Create instance.
|
||||
var execCmdLine bool
|
||||
instance, err := spn.New()
|
||||
|
@ -79,6 +75,10 @@ func main() {
|
|||
os.Exit(0)
|
||||
}
|
||||
|
||||
// Set default log level.
|
||||
log.SetLogLevel(log.WarningLevel)
|
||||
_ = log.Start()
|
||||
|
||||
// Start
|
||||
go func() {
|
||||
err = instance.Start()
|
||||
|
|
|
@ -225,14 +225,14 @@ func configureRegistry(mustLoadIndex bool) error {
|
|||
// Remove left over quotes.
|
||||
dataDir = strings.Trim(dataDir, `\"`)
|
||||
// Initialize data root.
|
||||
err := dataroot.Initialize(dataDir, 0o0755)
|
||||
err := dataroot.Initialize(dataDir, utils.PublicReadPermission)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to initialize data root: %w", err)
|
||||
}
|
||||
dataRoot = dataroot.Root()
|
||||
|
||||
// Initialize registry.
|
||||
err = registry.Initialize(dataRoot.ChildDir("updates", 0o0755))
|
||||
err = registry.Initialize(dataRoot.ChildDir("updates", utils.PublicReadPermission))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/safing/portmaster/base/utils"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
@ -24,7 +25,7 @@ var cleanStructureCmd = &cobra.Command{
|
|||
}
|
||||
|
||||
func cleanAndEnsureExecDir() error {
|
||||
execDir := dataRoot.ChildDir("exec", 0o777)
|
||||
execDir := dataRoot.ChildDir("exec", utils.PublicWritePermission)
|
||||
|
||||
// Clean up and remove exec dir.
|
||||
err := os.RemoveAll(execDir.Path)
|
||||
|
|
|
@ -179,14 +179,14 @@ func configureRegistry(mustLoadIndex bool) error {
|
|||
// Remove left over quotes.
|
||||
dataDir = strings.Trim(dataDir, `\"`)
|
||||
// Initialize data root.
|
||||
err := dataroot.Initialize(dataDir, 0o0755)
|
||||
err := dataroot.Initialize(dataDir, utils.PublicReadPermission)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to initialize data root: %w", err)
|
||||
}
|
||||
dataRoot = dataroot.Root()
|
||||
|
||||
// Initialize registry.
|
||||
err = registry.Initialize(dataRoot.ChildDir("updates", 0o0755))
|
||||
err = registry.Initialize(dataRoot.ChildDir("updates", utils.PublicReadPermission))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -196,7 +196,7 @@ func configureRegistry(mustLoadIndex bool) error {
|
|||
|
||||
func ensureLoggingDir() error {
|
||||
// set up logs root
|
||||
logsRoot = dataRoot.ChildDir("logs", 0o0777)
|
||||
logsRoot = dataRoot.ChildDir("logs", utils.PublicWritePermission)
|
||||
err := logsRoot.Ensure()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to initialize logs root (%q): %w", logsRoot.Path, err)
|
||||
|
|
|
@ -31,7 +31,7 @@ var rootCmd = &cobra.Command{
|
|||
}
|
||||
|
||||
registry = &updater.ResourceRegistry{}
|
||||
err = registry.Initialize(utils.NewDirStructure(absDistPath, 0o0755))
|
||||
err = registry.Initialize(utils.NewDirStructure(absDistPath, utils.PublicReadPermission))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/safing/portmaster/base/updater"
|
||||
"github.com/safing/portmaster/base/utils"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -63,7 +64,7 @@ func release(cmd *cobra.Command, args []string) error {
|
|||
fmt.Println("aborted...")
|
||||
return nil
|
||||
}
|
||||
symlinksDir := registry.StorageDir().ChildDir("latest", 0o755)
|
||||
symlinksDir := registry.StorageDir().ChildDir("latest", utils.PublicReadPermission)
|
||||
err = registry.CreateSymlinks(symlinksDir)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
43
go.mod
43
go.mod
|
@ -15,7 +15,7 @@ require (
|
|||
github.com/awalterschulze/gographviz v2.0.3+incompatible
|
||||
github.com/bluele/gcache v0.0.2
|
||||
github.com/brianvoe/gofakeit v3.18.0+incompatible
|
||||
github.com/cilium/ebpf v0.16.0
|
||||
github.com/cilium/ebpf v0.17.1
|
||||
github.com/coreos/go-iptables v0.8.0
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/dgraph-io/badger v1.6.2
|
||||
|
@ -34,10 +34,10 @@ require (
|
|||
github.com/hashicorp/go-version v1.7.0
|
||||
github.com/hectane/go-acl v0.0.0-20230122075934-ca0b05cb1adb
|
||||
github.com/jackc/puddle/v2 v2.2.2
|
||||
github.com/lmittmann/tint v1.0.5
|
||||
github.com/maruel/panicparse/v2 v2.3.1
|
||||
github.com/lmittmann/tint v1.0.6
|
||||
github.com/maruel/panicparse/v2 v2.4.0
|
||||
github.com/mat/besticon v3.12.0+incompatible
|
||||
github.com/mattn/go-colorable v0.1.13
|
||||
github.com/mattn/go-colorable v0.1.14
|
||||
github.com/mattn/go-isatty v0.0.20
|
||||
github.com/miekg/dns v1.1.62
|
||||
github.com/mitchellh/copystructure v1.2.0
|
||||
|
@ -62,22 +62,22 @@ require (
|
|||
github.com/varlink/go v0.4.0
|
||||
github.com/vincent-petithory/dataurl v1.0.0
|
||||
go.etcd.io/bbolt v1.3.11
|
||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f
|
||||
golang.org/x/image v0.22.0
|
||||
golang.org/x/net v0.31.0
|
||||
golang.org/x/sync v0.9.0
|
||||
golang.org/x/sys v0.27.0
|
||||
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8
|
||||
golang.org/x/image v0.23.0
|
||||
golang.org/x/net v0.34.0
|
||||
golang.org/x/sync v0.10.0
|
||||
golang.org/x/sys v0.29.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
zombiezen.com/go/sqlite v1.4.0
|
||||
)
|
||||
|
||||
require (
|
||||
al.essio.dev/pkg/shellescape v1.5.1 // indirect
|
||||
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect
|
||||
github.com/aead/ecdh v0.2.0 // indirect
|
||||
github.com/alessio/shellescape v1.4.2 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/danieljoos/wincred v1.2.1 // indirect
|
||||
github.com/dgraph-io/ristretto v0.1.1 // indirect
|
||||
github.com/danieljoos/wincred v1.2.2 // indirect
|
||||
github.com/dgraph-io/ristretto v0.2.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||
|
@ -85,7 +85,6 @@ require (
|
|||
github.com/godbus/dbus v4.1.0+incompatible // indirect
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||
github.com/golang/gddo v0.0.0-20210115222349-20d68f94ee1f // indirect
|
||||
github.com/golang/glog v1.2.1 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
|
@ -114,16 +113,16 @@ require (
|
|||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
github.com/zalando/go-keyring v0.2.5 // indirect
|
||||
github.com/zalando/go-keyring v0.2.6 // indirect
|
||||
github.com/zeebo/blake3 v0.2.4 // indirect
|
||||
golang.org/x/crypto v0.29.0 // indirect
|
||||
golang.org/x/crypto v0.32.0 // indirect
|
||||
golang.org/x/mod v0.22.0 // indirect
|
||||
golang.org/x/text v0.20.0 // indirect
|
||||
golang.org/x/tools v0.27.0 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
golang.org/x/tools v0.29.0 // indirect
|
||||
google.golang.org/protobuf v1.36.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
modernc.org/libc v1.61.2 // indirect
|
||||
modernc.org/mathutil v1.6.0 // indirect
|
||||
modernc.org/memory v1.8.0 // indirect
|
||||
modernc.org/sqlite v1.34.1 // indirect
|
||||
modernc.org/libc v1.61.7 // indirect
|
||||
modernc.org/mathutil v1.7.1 // indirect
|
||||
modernc.org/memory v1.8.1 // indirect
|
||||
modernc.org/sqlite v1.34.4 // indirect
|
||||
)
|
||||
|
|
123
go.sum
123
go.sum
|
@ -1,3 +1,5 @@
|
|||
al.essio.dev/pkg/shellescape v1.5.1 h1:86HrALUujYS/h+GtqoB26SBEdkWfmMI6FubjXlsXyho=
|
||||
al.essio.dev/pkg/shellescape v1.5.1/go.mod h1:6sIqp7X2P6mThCQ7twERpZTuigpr6KbZWtls1U8I890=
|
||||
cloud.google.com/go v0.16.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
fyne.io/systray v1.11.0 h1:D9HISlxSkx+jHSniMBR6fCFOUjk1x/OOOJLa9lJYAKg=
|
||||
fyne.io/systray v1.11.0/go.mod h1:RVwqP9nYMo7h5zViCBHri2FgjXF7H2cub7MAq4NSoLs=
|
||||
|
@ -16,8 +18,6 @@ github.com/aead/serpent v0.0.0-20160714141033-fba169763ea6 h1:5L8Mj9Co9sJVgW3TpY
|
|||
github.com/aead/serpent v0.0.0-20160714141033-fba169763ea6/go.mod h1:3HgLJ9d18kXMLQlJvIY3+FszZYMxCz8WfE2MQ7hDY0w=
|
||||
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
|
||||
github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
|
||||
github.com/alessio/shellescape v1.4.2 h1:MHPfaU+ddJ0/bYWpgIeUnQUqKrlJ1S7BfEYPM4uEoM0=
|
||||
github.com/alessio/shellescape v1.4.2/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
|
||||
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
|
@ -29,13 +29,12 @@ github.com/bradfitz/gomemcache v0.0.0-20170208213004-1952afaa557d/go.mod h1:PmM6
|
|||
github.com/brianvoe/gofakeit v3.18.0+incompatible h1:wDOmHc9DLG4nRjUVVaxA+CEglKOW72Y5+4WNxUIkjM8=
|
||||
github.com/brianvoe/gofakeit v3.18.0+incompatible/go.mod h1:kfwdRA90vvNhPutZWfH7WPaDzUjz+CZFqG+rPkOjGOc=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cilium/ebpf v0.5.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
||||
github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
|
||||
github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok=
|
||||
github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE=
|
||||
github.com/cilium/ebpf v0.17.1 h1:G8mzU81R2JA1nE5/8SRubzqvBMmAmri2VL8BIZPWvV0=
|
||||
github.com/cilium/ebpf v0.17.1/go.mod h1:vay2FaYSmIlv3r8dNACd4mW/OCaZLJKJOo+IHBvCIO8=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
github.com/coreos/go-iptables v0.8.0 h1:MPc2P89IhuVpLI7ETL/2tx3XZ61VeICZjYqDEgNsPRc=
|
||||
|
@ -43,18 +42,19 @@ github.com/coreos/go-iptables v0.8.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFE
|
|||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/danieljoos/wincred v1.2.1 h1:dl9cBrupW8+r5250DYkYxocLeZ1Y4vB1kxgtjxw8GQs=
|
||||
github.com/danieljoos/wincred v1.2.1/go.mod h1:uGaFL9fDn3OLTvzCGulzE+SzjEe5NGlh5FdCcyfPwps=
|
||||
github.com/danieljoos/wincred v1.2.2 h1:774zMFJrqaeYCK2W57BgAem/MLi6mtSE47MB6BOJ0i0=
|
||||
github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7nd/ogr0Uh8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgraph-io/badger v1.6.2 h1:mNw0qs90GVgGGWylh0umH5iag1j6n/PeJtNvL6KY/x8=
|
||||
github.com/dgraph-io/badger v1.6.2/go.mod h1:JW2yswe3V058sS0kZ2h/AXeDSqFjxnZcRrVH//y2UQE=
|
||||
github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
|
||||
github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8=
|
||||
github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
|
||||
github.com/dgraph-io/ristretto v0.2.0 h1:XAfl+7cmoUDWW/2Lx8TGZQjjxIQ2Ley9DSf52dru4WE=
|
||||
github.com/dgraph-io/ristretto v0.2.0/go.mod h1:8uBHCU/PBV4Ag0CJrP47b9Ofby5dqWNh4FicAdoqFNU=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y=
|
||||
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/dhaavi/go-notify v0.0.0-20190209221809-c404b1f22435 h1:AnwbdEI8eV3GzLM3SlrJlYmYa6OB5X8RwY4A8QJOCP0=
|
||||
github.com/dhaavi/go-notify v0.0.0-20190209221809-c404b1f22435/go.mod h1:EMJ8XWTopp8OLRBMUm9vHE8Wn48CNpU21HM817OKNrc=
|
||||
github.com/dhaavi/winres v0.2.2 h1:SUago7FwhgLSMyDdeuV6enBZ+ZQSl0KwcnbWzvlfBls=
|
||||
|
@ -96,9 +96,6 @@ github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGw
|
|||
github.com/golang/gddo v0.0.0-20180823221919-9d8ff1c67be5/go.mod h1:xEhNfoBDX1hzLm2Nf80qUvZ2sVwoMZ8d6IE2SrsQfh4=
|
||||
github.com/golang/gddo v0.0.0-20210115222349-20d68f94ee1f h1:16RtHeWGkJMc80Etb8RPCcKevXGldr57+LOyZt8zOlg=
|
||||
github.com/golang/gddo v0.0.0-20210115222349-20d68f94ee1f/go.mod h1:ijRvpgDJDI262hYq/IQVYgf8hd8IHUs93Ol0kvMBAx4=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4=
|
||||
github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
|
||||
github.com/golang/lint v0.0.0-20170918230701-e5d664eb928e/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
|
@ -171,21 +168,18 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/lmittmann/tint v1.0.5 h1:NQclAutOfYsqs2F1Lenue6OoWCajs5wJcP3DfWVpePw=
|
||||
github.com/lmittmann/tint v1.0.5/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE=
|
||||
github.com/lmittmann/tint v1.0.6 h1:vkkuDAZXc0EFGNzYjWcV0h7eEX+uujH48f/ifSkJWgc=
|
||||
github.com/lmittmann/tint v1.0.6/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE=
|
||||
github.com/magiconair/properties v1.7.4-0.20170902060319-8d7837e64d3c/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/maruel/panicparse/v2 v2.3.1 h1:NtJavmbMn0DyzmmSStE8yUsmPZrZmudPH7kplxBinOA=
|
||||
github.com/maruel/panicparse/v2 v2.3.1/go.mod h1:s3UmQB9Fm/n7n/prcD2xBGDkwXD6y2LeZnhbEXvs9Dg=
|
||||
github.com/maruel/panicparse/v2 v2.4.0 h1:yQKMIbQ0DKfinzVkTkcUzQyQ60UCiNnYfR7PWwTs2VI=
|
||||
github.com/maruel/panicparse/v2 v2.4.0/go.mod h1:nOY2OKe8csO3F3SA5+hsxot05JLgukrF54B9x88fVp4=
|
||||
github.com/mat/besticon v3.12.0+incompatible h1:1KTD6wisfjfnX+fk9Kx/6VEZL+MAW1LhCkL9Q47H9Bg=
|
||||
github.com/mat/besticon v3.12.0+incompatible/go.mod h1:mA1auQYHt6CW5e7L9HJLmqVQC8SzNk2gVwouO0AbiEU=
|
||||
github.com/mattn/go-colorable v0.0.10-0.20170816031813-ad5389df28cd/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.2/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mdlayher/ethtool v0.0.0-20210210192532-2b88debcdd43/go.mod h1:+t7E0lkKfbBsebllff1xdTmyJt8lH37niI6kwFk9OTo=
|
||||
|
@ -211,7 +205,6 @@ github.com/mdlayher/socket v0.1.0/go.mod h1:mYV5YIZAfHh4dzDVzI8x8tWLWCliuX8Mon5A
|
|||
github.com/mdlayher/socket v0.1.1/go.mod h1:mYV5YIZAfHh4dzDVzI8x8tWLWCliuX8Mon5Awbj+qDs=
|
||||
github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos=
|
||||
github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ=
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
|
||||
github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
|
||||
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
||||
|
@ -329,8 +322,8 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
|
|||
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
github.com/zalando/go-keyring v0.2.5 h1:Bc2HHpjALryKD62ppdEzaFG6VxL6Bc+5v0LYpN8Lba8=
|
||||
github.com/zalando/go-keyring v0.2.5/go.mod h1:HL4k+OXQfJUWaMnqyuSOc0drfGPX2b51Du6K+MRgZMk=
|
||||
github.com/zalando/go-keyring v0.2.6 h1:r7Yc3+H+Ux0+M72zacZoItR3UDxeWfKTcabvkI8ua9s=
|
||||
github.com/zalando/go-keyring v0.2.6/go.mod h1:2TCrxYrbUNYfNS/Kgy/LSrkSQzZ5UPVH85RwfczwvcI=
|
||||
github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
|
||||
github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
|
||||
github.com/zeebo/blake3 v0.2.4 h1:KYQPkhpRtcqh0ssGYcKLG1JYvddkEA8QwCM/yBqhaZI=
|
||||
|
@ -344,12 +337,12 @@ golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnf
|
|||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
|
||||
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
|
||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo=
|
||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak=
|
||||
golang.org/x/image v0.22.0 h1:UtK5yLUzilVrkjMAZAZ34DXGpASN8i8pj8g+O+yd10g=
|
||||
golang.org/x/image v0.22.0/go.mod h1:9hPFhljd4zZ1GNSIZJ49sqbp45GKK9t6w+iXvGqZUz4=
|
||||
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
|
||||
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
||||
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA=
|
||||
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
|
||||
golang.org/x/image v0.23.0 h1:HseQ7c2OpPKTPVzNjG5fwJsOTCiiwS4QdsYi5XU6H68=
|
||||
golang.org/x/image v0.23.0/go.mod h1:wJJBTdLfCCf3tiHa1fNxpZmUI4mmoZvwMCPP0ddoNKY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
|
@ -378,15 +371,15 @@ golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qx
|
|||
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220107192237-5cfca573fb4d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
|
||||
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
|
||||
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
|
||||
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
||||
golang.org/x/oauth2 v0.0.0-20170912212905-13449ad91cb2/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20170517211232-f52d1811a629/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
|
||||
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -412,7 +405,6 @@ golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
@ -420,13 +412,10 @@ golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
||||
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
@ -434,16 +423,16 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
|||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
|
||||
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/time v0.0.0-20170424234030-8be79e1e0910/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
||||
golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o=
|
||||
golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q=
|
||||
golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE=
|
||||
golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -452,8 +441,8 @@ google.golang.org/api v0.0.0-20170921000349-586095a6e407/go.mod h1:4mhQ8q/RsB7i+
|
|||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20170918111702-1e559d0a00ee/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/grpc v1.2.1-0.20170921194603-d4b75ebd4f9f/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
google.golang.org/protobuf v1.36.2 h1:R8FeyR1/eLmkutZOM5CWghmo5itiG9z0ktFlTVLuTmU=
|
||||
google.golang.org/protobuf v1.36.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
@ -465,28 +454,28 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.2.1/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY=
|
||||
honnef.co/go/tools v0.2.2/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY=
|
||||
modernc.org/cc/v4 v4.23.1 h1:WqJoPL3x4cUufQVHkXpXX7ThFJ1C4ik80i2eXEXbhD8=
|
||||
modernc.org/cc/v4 v4.23.1/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
|
||||
modernc.org/ccgo/v4 v4.22.3 h1:C7AW89Zw3kygesTQWBzApwIn9ldM+cb/plrTIKq41Os=
|
||||
modernc.org/ccgo/v4 v4.22.3/go.mod h1:Dz7n0/UkBbH3pnYaxgi1mFSfF4REqUOZNziphZASx6k=
|
||||
modernc.org/cc/v4 v4.24.4 h1:TFkx1s6dCkQpd6dKurBNmpo+G8Zl4Sq/ztJ+2+DEsh0=
|
||||
modernc.org/cc/v4 v4.24.4/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
|
||||
modernc.org/ccgo/v4 v4.23.10 h1:DnDZT/H6TtoJvQmVf7d8W+lVqEZpIJY/+0ENFh1LIHE=
|
||||
modernc.org/ccgo/v4 v4.23.10/go.mod h1:vdN4h2WR5aEoNondUx26K7G8X+nuBscYnAEWSRmN2/0=
|
||||
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
|
||||
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
|
||||
modernc.org/gc/v2 v2.5.0 h1:bJ9ChznK1L1mUtAQtxi0wi5AtAs5jQuw4PrPHO5pb6M=
|
||||
modernc.org/gc/v2 v2.5.0/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
|
||||
modernc.org/libc v1.61.2 h1:dkO4DlowfClcJYsvf/RiK6fUwvzCQTmB34bJLt0CAGQ=
|
||||
modernc.org/libc v1.61.2/go.mod h1:4QGjNyX3h+rn7V5oHpJY2yH0QN6frt1X+5BkXzwLPCo=
|
||||
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
||||
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
|
||||
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
|
||||
modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
|
||||
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
|
||||
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
|
||||
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
|
||||
modernc.org/sqlite v1.34.1 h1:u3Yi6M0N8t9yKRDwhXcyp1eS5/ErhPTBggxWFuR6Hfk=
|
||||
modernc.org/sqlite v1.34.1/go.mod h1:pXV2xHxhzXZsgT/RtTFAPY6JJDEvOTcTdwADQCCWD4k=
|
||||
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
|
||||
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
|
||||
modernc.org/gc/v2 v2.6.1 h1:+Qf6xdG8l7B27TQ8D8lw/iFMUj1RXRBOuMUWziJOsk8=
|
||||
modernc.org/gc/v2 v2.6.1/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
|
||||
modernc.org/libc v1.61.7 h1:exz8rasFniviSgh3dH7QBnQHqYh9lolA5hVYfsiwkfo=
|
||||
modernc.org/libc v1.61.7/go.mod h1:xspSrXRNVSfWfcfqgvZDVe/Hw5kv4FVC6IRfoms5v/0=
|
||||
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
|
||||
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
|
||||
modernc.org/memory v1.8.1 h1:HS1HRg1jEohnuONobEq2WrLEhLyw8+J42yLFTnllm2A=
|
||||
modernc.org/memory v1.8.1/go.mod h1:ZbjSvMO5NQ1A2i3bWeDiVMxIorXwdClKE/0SZ+BMotU=
|
||||
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
|
||||
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
|
||||
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
|
||||
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
|
||||
modernc.org/sqlite v1.34.4 h1:sjdARozcL5KJBvYQvLlZEmctRgW9xqIZc2ncN7PU0P8=
|
||||
modernc.org/sqlite v1.34.4/go.mod h1:3QQFCG2SEMtc2nv+Wq4cQCH7Hjcg+p/RMlS1XK+zwbk=
|
||||
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
|
||||
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
|
||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
zombiezen.com/go/sqlite v1.4.0 h1:N1s3RIljwtp4541Y8rM880qgGIgq3fTD2yks1xftnKU=
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"github.com/safing/portmaster/base/api"
|
||||
"github.com/safing/portmaster/base/dataroot"
|
||||
"github.com/safing/portmaster/base/info"
|
||||
"github.com/safing/portmaster/base/utils"
|
||||
"github.com/safing/portmaster/service/mgr"
|
||||
)
|
||||
|
||||
|
@ -54,7 +55,7 @@ func prep(instance instance) error {
|
|||
}
|
||||
|
||||
// initialize structure
|
||||
err := dataroot.Initialize(dataDir, 0o0755)
|
||||
err := dataroot.Initialize(dataDir, utils.PublicReadPermission)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ var (
|
|||
var cache = database.NewInterface(&database.Options{
|
||||
Local: true,
|
||||
Internal: true,
|
||||
CacheSize: 2 ^ 8,
|
||||
CacheSize: 256,
|
||||
})
|
||||
|
||||
// getFileFunc is the function used to get a file from
|
||||
|
|
|
@ -4,7 +4,7 @@ import "time"
|
|||
|
||||
// SleepyTicker is wrapper over time.Ticker that respects the sleep mode of the module.
|
||||
type SleepyTicker struct {
|
||||
ticker time.Ticker
|
||||
ticker *time.Ticker
|
||||
normalDuration time.Duration
|
||||
sleepDuration time.Duration
|
||||
sleepMode bool
|
||||
|
@ -16,7 +16,7 @@ type SleepyTicker struct {
|
|||
// If sleepDuration is set to 0 ticker will not tick during sleep.
|
||||
func NewSleepyTicker(normalDuration time.Duration, sleepDuration time.Duration) *SleepyTicker {
|
||||
st := &SleepyTicker{
|
||||
ticker: *time.NewTicker(normalDuration),
|
||||
ticker: time.NewTicker(normalDuration),
|
||||
normalDuration: normalDuration,
|
||||
sleepDuration: sleepDuration,
|
||||
sleepMode: false,
|
||||
|
|
57
service/mgr/sleepyticker_test.go
Normal file
57
service/mgr/sleepyticker_test.go
Normal file
|
@ -0,0 +1,57 @@
|
|||
package mgr
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestSleepyTickerStop(t *testing.T) {
|
||||
normalDuration := 100 * time.Millisecond
|
||||
sleepDuration := 200 * time.Millisecond
|
||||
|
||||
st := NewSleepyTicker(normalDuration, sleepDuration)
|
||||
st.Stop() // no panic expected here
|
||||
}
|
||||
|
||||
func TestSleepyTicker(t *testing.T) {
|
||||
normalDuration := 100 * time.Millisecond
|
||||
sleepDuration := 200 * time.Millisecond
|
||||
|
||||
st := NewSleepyTicker(normalDuration, sleepDuration)
|
||||
|
||||
// Test normal mode
|
||||
select {
|
||||
case <-st.Wait():
|
||||
// Expected tick
|
||||
case <-time.After(normalDuration + 50*time.Millisecond):
|
||||
t.Error("expected tick in normal mode")
|
||||
}
|
||||
|
||||
// Test sleep mode
|
||||
st.SetSleep(true)
|
||||
select {
|
||||
case <-st.Wait():
|
||||
// Expected tick
|
||||
case <-time.After(sleepDuration + 50*time.Millisecond):
|
||||
t.Error("expected tick in sleep mode")
|
||||
}
|
||||
|
||||
// Test sleep mode with sleepDuration == 0
|
||||
st = NewSleepyTicker(normalDuration, 0)
|
||||
st.SetSleep(true)
|
||||
select {
|
||||
case <-st.Wait():
|
||||
t.Error("did not expect tick when sleepDuration is 0")
|
||||
case <-time.After(normalDuration):
|
||||
// Expected no tick
|
||||
}
|
||||
|
||||
// Test stopping the ticker
|
||||
st.Stop()
|
||||
select {
|
||||
case <-st.Wait():
|
||||
t.Error("did not expect tick after stopping the ticker")
|
||||
case <-time.After(normalDuration):
|
||||
// Expected no tick
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ import (
|
|||
"github.com/safing/portmaster/base/config"
|
||||
"github.com/safing/portmaster/base/dataroot"
|
||||
"github.com/safing/portmaster/base/log"
|
||||
"github.com/safing/portmaster/base/utils"
|
||||
"github.com/safing/portmaster/service/netquery/orm"
|
||||
"github.com/safing/portmaster/service/network"
|
||||
"github.com/safing/portmaster/service/network/netutils"
|
||||
|
@ -127,7 +128,7 @@ type (
|
|||
// Note that write connections are serialized by the Database object before being
|
||||
// handed over to SQLite.
|
||||
func New(dbPath string) (*Database, error) {
|
||||
historyParentDir := dataroot.Root().ChildDir("databases", 0o700)
|
||||
historyParentDir := dataroot.Root().ChildDir("databases", utils.AdminOnlyPermission)
|
||||
if err := historyParentDir.Ensure(); err != nil {
|
||||
return nil, fmt.Errorf("failed to ensure database directory exists: %w", err)
|
||||
}
|
||||
|
@ -225,7 +226,7 @@ func (db *Database) Close() error {
|
|||
|
||||
// VacuumHistory rewrites the history database in order to purge deleted records.
|
||||
func VacuumHistory(ctx context.Context) (err error) {
|
||||
historyParentDir := dataroot.Root().ChildDir("databases", 0o700)
|
||||
historyParentDir := dataroot.Root().ChildDir("databases", utils.AdminOnlyPermission)
|
||||
if err := historyParentDir.Ensure(); err != nil {
|
||||
return fmt.Errorf("failed to ensure database directory exists: %w", err)
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/safing/portmaster/base/database/migration"
|
||||
"github.com/safing/portmaster/base/dataroot"
|
||||
"github.com/safing/portmaster/base/log"
|
||||
"github.com/safing/portmaster/base/utils"
|
||||
_ "github.com/safing/portmaster/service/core/base"
|
||||
"github.com/safing/portmaster/service/mgr"
|
||||
"github.com/safing/portmaster/service/profile/binmeta"
|
||||
|
@ -70,7 +71,7 @@ func prep() error {
|
|||
}
|
||||
|
||||
// Setup icon storage location.
|
||||
iconsDir := dataroot.Root().ChildDir("databases", 0o0700).ChildDir("icons", 0o0700)
|
||||
iconsDir := dataroot.Root().ChildDir("databases", utils.AdminOnlyPermission).ChildDir("icons", utils.AdminOnlyPermission)
|
||||
if err := iconsDir.Ensure(); err != nil {
|
||||
return fmt.Errorf("failed to create/check icons directory: %w", err)
|
||||
}
|
||||
|
|
|
@ -510,7 +510,7 @@ func setScopedResolvers(resolvers []*Resolver) {
|
|||
for _, resolver := range resolvers {
|
||||
if resolver.Info.IPScope.IsLAN() {
|
||||
localResolvers = append(localResolvers, resolver)
|
||||
} else if _, err := netenv.GetLocalNetwork(resolver.Info.IP); err != nil {
|
||||
} else if net, _ := netenv.GetLocalNetwork(resolver.Info.IP); net != nil {
|
||||
localResolvers = append(localResolvers, resolver)
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/safing/portmaster/base/api"
|
||||
"github.com/safing/portmaster/base/dataroot"
|
||||
"github.com/safing/portmaster/base/log"
|
||||
"github.com/safing/portmaster/base/utils"
|
||||
"github.com/safing/portmaster/service/mgr"
|
||||
)
|
||||
|
||||
|
@ -27,7 +28,7 @@ func start() error {
|
|||
// may seem dangerous, but proper permission on the parent directory provide
|
||||
// (some) protection.
|
||||
// Processes must _never_ read from this directory.
|
||||
err := dataroot.Root().ChildDir("exec", 0o0777).Ensure()
|
||||
err := dataroot.Root().ChildDir("exec", utils.PublicWritePermission).Ensure()
|
||||
if err != nil {
|
||||
log.Warningf("ui: failed to create safe exec dir: %s", err)
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/safing/portmaster/base/dataroot"
|
||||
"github.com/safing/portmaster/base/log"
|
||||
"github.com/safing/portmaster/base/updater"
|
||||
"github.com/safing/portmaster/base/utils"
|
||||
"github.com/safing/portmaster/service/mgr"
|
||||
"github.com/safing/portmaster/service/updates/helper"
|
||||
)
|
||||
|
@ -138,7 +139,7 @@ func start() error {
|
|||
}
|
||||
|
||||
// initialize
|
||||
err = registry.Initialize(dataroot.Root().ChildDir(updatesDirName, 0o0755))
|
||||
err = registry.Initialize(dataroot.Root().ChildDir(updatesDirName, utils.PublicReadPermission))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hectane/go-acl"
|
||||
processInfo "github.com/shirou/gopsutil/process"
|
||||
"github.com/tevino/abool"
|
||||
|
||||
|
@ -21,6 +20,7 @@ import (
|
|||
"github.com/safing/portmaster/base/notifications"
|
||||
"github.com/safing/portmaster/base/rng"
|
||||
"github.com/safing/portmaster/base/updater"
|
||||
"github.com/safing/portmaster/base/utils"
|
||||
"github.com/safing/portmaster/base/utils/renameio"
|
||||
"github.com/safing/portmaster/service/mgr"
|
||||
"github.com/safing/portmaster/service/updates/helper"
|
||||
|
@ -351,17 +351,15 @@ func upgradeBinary(fileToUpgrade string, file *updater.File) error {
|
|||
|
||||
// check permissions
|
||||
if onWindows {
|
||||
err = acl.Chmod(fileToUpgrade, 0o0755)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to set permissions on %s: %w", fileToUpgrade, err)
|
||||
}
|
||||
_ = utils.SetExecPermission(fileToUpgrade, utils.PublicReadPermission)
|
||||
} else {
|
||||
perm := utils.PublicReadPermission
|
||||
info, err := os.Stat(fileToUpgrade)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get file info on %s: %w", fileToUpgrade, err)
|
||||
}
|
||||
if info.Mode() != 0o0755 {
|
||||
err := os.Chmod(fileToUpgrade, 0o0755) //nolint:gosec // Set execute permissions.
|
||||
if info.Mode() != perm.AsUnixDirExecPermission() {
|
||||
err = utils.SetExecPermission(fileToUpgrade, perm)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to set permissions on %s: %w", fileToUpgrade, err)
|
||||
}
|
||||
|
|
25
spn/testing/README.md
Normal file
25
spn/testing/README.md
Normal file
|
@ -0,0 +1,25 @@
|
|||
# Testing Port17
|
||||
|
||||
## Simple Docker Setup
|
||||
|
||||
Run `run.sh` to start the docker compose test network.
|
||||
Then, connect to the test network, by starting the core with the "test" spn map and the correct bootstrap file.
|
||||
|
||||
Run `stop.sh` to remove all docker resources again.
|
||||
|
||||
Setup Guide can be found in the directory.
|
||||
|
||||
## Advanced Setup with Shadow
|
||||
|
||||
For advanced testing we use [shadow](https://github.com/shadow/shadow).
|
||||
The following section will help you set up shadow and will guide you how to test Port17 in a local Shadow environment.
|
||||
|
||||
### Setting up
|
||||
|
||||
Download the docker version from here: [https://security.cs.georgetown.edu/shadow-docker-images/shadow-standalone.tar.gz](https://security.cs.georgetown.edu/shadow-docker-images/shadow-standalone.tar.gz)
|
||||
|
||||
Then import the image into docker with `gunzip -c shadow-standalone.tar.gz | sudo docker load`.
|
||||
|
||||
### Running
|
||||
|
||||
Execute `sudo docker run -t -i -u shadow shadow-standalone /bin/bash` to start an interactive container with shadow.
|
50
spn/testing/simple/README.md
Normal file
50
spn/testing/simple/README.md
Normal file
|
@ -0,0 +1,50 @@
|
|||
# Setup Guide
|
||||
|
||||
1. Build SPN Hub
|
||||
|
||||
```
|
||||
cd ../../../cmds/hub/
|
||||
./build
|
||||
```
|
||||
|
||||
2. Reset any previous state (for a fresh test)
|
||||
|
||||
```
|
||||
./reset-databases.sh
|
||||
```
|
||||
|
||||
3. Change compose file and config template as required
|
||||
|
||||
Files:
|
||||
- `docker-compose.yml`
|
||||
- `config-template.json`
|
||||
|
||||
4. Start test network
|
||||
|
||||
```
|
||||
./run.sh
|
||||
```
|
||||
|
||||
5. Option 1: Join as Hub
|
||||
|
||||
For testing just one Hub with a different build or config, you can simply use `./join.sh` to join the network with the most recently build hub binary.
|
||||
|
||||
6. Option 2: Join as Portmaster
|
||||
|
||||
For connecting to the SPN test network with Portmaster, execute portmaster like this:
|
||||
|
||||
```
|
||||
sudo ../../../cmds/portmaster-core/portmaster-core --disable-shutdown-event --devmode --log debug --data /opt/safing/portmaster --spn-map test --bootstrap-file ./testdata/shared/bootstrap.dsd
|
||||
```
|
||||
|
||||
Note:
|
||||
This uses the same portmaster data and config as your installed version.
|
||||
As the SPN Test net operates under a different ID ("test" instead of "main"), this will not pollute the SPN state of your installed Portmaster.
|
||||
|
||||
7. Stop the test net
|
||||
|
||||
This is important, as just stopping the `./run.sh` script will leave you with interfaces with public IPs!
|
||||
|
||||
```
|
||||
./stop.sh
|
||||
```
|
41
spn/testing/simple/clientsim.sh
Executable file
41
spn/testing/simple/clientsim.sh
Executable file
|
@ -0,0 +1,41 @@
|
|||
#!/bin/bash
|
||||
|
||||
cd "$( dirname "${BASH_SOURCE[0]}" )"
|
||||
|
||||
realpath() {
|
||||
path=`eval echo "$1"`
|
||||
folder=$(dirname "$path")
|
||||
echo $(cd "$folder"; pwd)/$(basename "$path");
|
||||
}
|
||||
|
||||
if [[ ! -f "../../client" ]]; then
|
||||
echo "please compile client.go in main directory (output: client)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
bin_path="$(realpath ../../client)"
|
||||
data_path="$(realpath ./testdata)"
|
||||
if [[ ! -d "$data_path" ]]; then
|
||||
mkdir "$data_path"
|
||||
fi
|
||||
shared_path="$(realpath ./testdata/shared)"
|
||||
if [[ ! -d "$shared_path" ]]; then
|
||||
mkdir "$shared_path"
|
||||
fi
|
||||
|
||||
docker network ls | grep spn-simpletest-network >/dev/null 2>&1
|
||||
if [[ $? -ne 0 ]]; then
|
||||
docker network create spn-simpletest-network --subnet 6.0.0.0/24
|
||||
fi
|
||||
|
||||
docker run -ti --rm \
|
||||
--name spn-simpletest-clientsim \
|
||||
--network spn-simpletest-network \
|
||||
-v $bin_path:/opt/client:ro \
|
||||
-v $data_path/clientsim:/opt/data \
|
||||
-v $shared_path:/opt/shared \
|
||||
--entrypoint /opt/client \
|
||||
toolset.safing.network/dev \
|
||||
--data /opt/data \
|
||||
--bootstrap-file /opt/shared/bootstrap.dsd \
|
||||
--log trace $*
|
19
spn/testing/simple/config-template.json
Normal file
19
spn/testing/simple/config-template.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"core": {
|
||||
"log": {
|
||||
"level": "trace"
|
||||
},
|
||||
"metrics": {
|
||||
"instance": "test_$HUBNAME",
|
||||
"push": ""
|
||||
}
|
||||
},
|
||||
"spn": {
|
||||
"publicHub": {
|
||||
"name": "test-$HUBNAME",
|
||||
"transports": ["http:80", "http:8080", "tcp:17"],
|
||||
"allowUnencrypted": true,
|
||||
"bindToAdvertised": true
|
||||
}
|
||||
}
|
||||
}
|
139
spn/testing/simple/docker-compose.yml
Normal file
139
spn/testing/simple/docker-compose.yml
Normal file
|
@ -0,0 +1,139 @@
|
|||
version: "2.4"
|
||||
|
||||
networks:
|
||||
default:
|
||||
ipam:
|
||||
driver: default
|
||||
config:
|
||||
- subnet: 6.0.0.0/24
|
||||
|
||||
services:
|
||||
hub1:
|
||||
container_name: spn-test-simple-hub1
|
||||
hostname: hub1
|
||||
image: toolset.safing.network/dev
|
||||
entrypoint: "/opt/shared/entrypoint.sh"
|
||||
volumes:
|
||||
- ${SPN_TEST_BIN}:/opt/hub1:ro
|
||||
- ${SPN_TEST_DATA_DIR}/hub1:/opt/data
|
||||
- ${SPN_TEST_SHARED_DATA_DIR}:/opt/shared
|
||||
networks:
|
||||
default:
|
||||
ipv4_address: 6.0.0.11
|
||||
|
||||
hub2:
|
||||
container_name: spn-test-simple-hub2
|
||||
hostname: hub2
|
||||
image: alpine
|
||||
entrypoint: "/opt/shared/entrypoint.sh"
|
||||
volumes:
|
||||
- ${SPN_TEST_BIN}:/opt/hub2:ro
|
||||
- ${SPN_TEST_DATA_DIR}/hub2:/opt/data
|
||||
- ${SPN_TEST_SHARED_DATA_DIR}:/opt/shared
|
||||
networks:
|
||||
default:
|
||||
ipv4_address: 6.0.0.12
|
||||
|
||||
hub3:
|
||||
container_name: spn-test-simple-hub3
|
||||
hostname: hub3
|
||||
image: toolset.safing.network/dev
|
||||
entrypoint: "/opt/shared/entrypoint.sh"
|
||||
volumes:
|
||||
- ${SPN_TEST_BIN}:/opt/hub3:ro
|
||||
- ${SPN_TEST_DATA_DIR}/hub3:/opt/data
|
||||
- ${SPN_TEST_SHARED_DATA_DIR}:/opt/shared
|
||||
networks:
|
||||
default:
|
||||
ipv4_address: 6.0.0.13
|
||||
|
||||
hub4:
|
||||
container_name: spn-test-simple-hub4
|
||||
hostname: hub4
|
||||
image: toolset.safing.network/dev
|
||||
entrypoint: "/opt/shared/entrypoint.sh"
|
||||
volumes:
|
||||
- ${SPN_TEST_BIN}:/opt/hub4:ro
|
||||
- ${SPN_TEST_DATA_DIR}/hub4:/opt/data
|
||||
- ${SPN_TEST_SHARED_DATA_DIR}:/opt/shared
|
||||
networks:
|
||||
default:
|
||||
ipv4_address: 6.0.0.14
|
||||
|
||||
hub5:
|
||||
container_name: spn-test-simple-hub5
|
||||
hostname: hub5
|
||||
image: toolset.safing.network/dev
|
||||
entrypoint: "/opt/shared/entrypoint.sh"
|
||||
volumes:
|
||||
- ${SPN_TEST_BIN}:/opt/hub5:ro
|
||||
- ${SPN_TEST_DATA_DIR}/hub5:/opt/data
|
||||
- ${SPN_TEST_SHARED_DATA_DIR}:/opt/shared
|
||||
networks:
|
||||
default:
|
||||
ipv4_address: 6.0.0.15
|
||||
|
||||
hub6:
|
||||
container_name: spn-test-simple-hub6
|
||||
hostname: hub6
|
||||
image: toolset.safing.network/dev
|
||||
entrypoint: "/opt/shared/entrypoint.sh"
|
||||
volumes:
|
||||
- ${SPN_TEST_OLD_BIN}:/opt/hub6:ro
|
||||
- ${SPN_TEST_DATA_DIR}/hub6:/opt/data
|
||||
- ${SPN_TEST_SHARED_DATA_DIR}:/opt/shared
|
||||
networks:
|
||||
default:
|
||||
ipv4_address: 6.0.0.16
|
||||
|
||||
hub7:
|
||||
container_name: spn-test-simple-hub7
|
||||
hostname: hub7
|
||||
image: toolset.safing.network/dev
|
||||
entrypoint: "/opt/shared/entrypoint.sh"
|
||||
volumes:
|
||||
- ${SPN_TEST_OLD_BIN}:/opt/hub7:ro
|
||||
- ${SPN_TEST_DATA_DIR}/hub7:/opt/data
|
||||
- ${SPN_TEST_SHARED_DATA_DIR}:/opt/shared
|
||||
networks:
|
||||
default:
|
||||
ipv4_address: 6.0.0.17
|
||||
|
||||
hub8:
|
||||
container_name: spn-test-simple-hub8
|
||||
hostname: hub8
|
||||
image: toolset.safing.network/dev
|
||||
entrypoint: "/opt/shared/entrypoint.sh"
|
||||
volumes:
|
||||
- ${SPN_TEST_OLD_BIN}:/opt/hub8:ro
|
||||
- ${SPN_TEST_DATA_DIR}/hub8:/opt/data
|
||||
- ${SPN_TEST_SHARED_DATA_DIR}:/opt/shared
|
||||
networks:
|
||||
default:
|
||||
ipv4_address: 6.0.0.18
|
||||
|
||||
hub9:
|
||||
container_name: spn-test-simple-hub9
|
||||
hostname: hub9
|
||||
image: toolset.safing.network/dev
|
||||
entrypoint: "/opt/shared/entrypoint.sh"
|
||||
volumes:
|
||||
- ${SPN_TEST_OLD_BIN}:/opt/hub9:ro
|
||||
- ${SPN_TEST_DATA_DIR}/hub9:/opt/data
|
||||
- ${SPN_TEST_SHARED_DATA_DIR}:/opt/shared
|
||||
networks:
|
||||
default:
|
||||
ipv4_address: 6.0.0.19
|
||||
|
||||
hub10:
|
||||
container_name: spn-test-simple-hub10
|
||||
hostname: hub10
|
||||
image: toolset.safing.network/dev
|
||||
entrypoint: "/opt/shared/entrypoint.sh"
|
||||
volumes:
|
||||
- ${SPN_TEST_OLD_BIN}:/opt/hub10:ro
|
||||
- ${SPN_TEST_DATA_DIR}/hub10:/opt/data
|
||||
- ${SPN_TEST_SHARED_DATA_DIR}:/opt/shared
|
||||
networks:
|
||||
default:
|
||||
ipv4_address: 6.0.0.20
|
17
spn/testing/simple/entrypoint.sh
Executable file
17
spn/testing/simple/entrypoint.sh
Executable file
|
@ -0,0 +1,17 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Get hostname.
|
||||
HUBNAME=$HOSTNAME
|
||||
if [ "$HUBNAME" = "" ]; then
|
||||
HUBNAME=$(cat /etc/hostname)
|
||||
fi
|
||||
export HUBNAME
|
||||
|
||||
# Read, process and write config.
|
||||
cat /opt/shared/config-template.json | sed "s/\$HUBNAME/$HUBNAME/g" > /opt/data/config.json
|
||||
|
||||
# Get binary to start.
|
||||
BIN=$(ls /opt/ | grep hub)
|
||||
|
||||
# Start Hub.
|
||||
/opt/$BIN --data /opt/data --log trace --spn-map test --bootstrap-file /opt/shared/bootstrap.dsd --api-address 0.0.0.0:817 --devmode
|
35
spn/testing/simple/inject-intel.sh
Executable file
35
spn/testing/simple/inject-intel.sh
Executable file
|
@ -0,0 +1,35 @@
|
|||
#!/bin/bash
|
||||
|
||||
cd "$( dirname "${BASH_SOURCE[0]}" )"
|
||||
|
||||
MAIN_INTEL_FILE="intel-testnet.json"
|
||||
|
||||
if [[ ! -f $MAIN_INTEL_FILE ]]; then
|
||||
echo "missing $MAIN_INTEL_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "if the containing directory cannot be created, you might need to adjust permissions, as nodes are run with root in test containers..."
|
||||
echo "$ sudo chmod -R 777 data/hub*/updates"
|
||||
echo "starting to update..."
|
||||
|
||||
for hubDir in data/hub*; do
|
||||
# Build destination path
|
||||
hubIntelFile="${hubDir}/updates/all/intel/spn/main-intel_v0-0-0.dsd"
|
||||
|
||||
# Copy file
|
||||
mkdir -p "${hubDir}/updates/all/intel/spn"
|
||||
echo -n "J" > "$hubIntelFile"
|
||||
cat $MAIN_INTEL_FILE >> "$hubIntelFile"
|
||||
|
||||
echo "updated $hubIntelFile"
|
||||
done
|
||||
|
||||
if [[ -d /var/lib/portmaster ]]; then
|
||||
echo "updating intel for local portmaster installation..."
|
||||
|
||||
portmasterSPNIntelFile="/var/lib/portmaster/updates/all/intel/spn/main-intel_v0-0-0.dsd"
|
||||
echo -n "J" > "$portmasterSPNIntelFile"
|
||||
cat $MAIN_INTEL_FILE >> "$portmasterSPNIntelFile"
|
||||
echo "updated $portmasterSPNIntelFile"
|
||||
fi
|
25
spn/testing/simple/intel-client.yaml
Normal file
25
spn/testing/simple/intel-client.yaml
Normal file
|
@ -0,0 +1,25 @@
|
|||
# Get current list of IDs from test net:
|
||||
# curl http://127.0.0.1:817/api/v1/spn/map/test/pins | jq ".[] | .ID"
|
||||
# Then import into test client with:
|
||||
# curl -X POST --upload-file intel-client.yaml http://127.0.0.1:817/api/v1/spn/map/test/intel/update
|
||||
Hubs:
|
||||
Zwm48YWWFGdwXjhE1MyEkWfqxPr9DiUBoXpusTZ1FMQnuK:
|
||||
Trusted: true
|
||||
Zwu5LkkbfCbAcYxWG3vtWF1VvWjgWpc1GJfkwRdLFNtytV:
|
||||
Trusted: true
|
||||
ZwuQpz5CqYmYoLnt9KXQ8oxnmosBzfrCYwCGhxT4fsG1Dz:
|
||||
Trusted: true
|
||||
ZwwmC3dHzr7J6XW9mc2KD6FDNuXwPVJUFi9dLnDSNMyjLk:
|
||||
Trusted: true
|
||||
ZwxSBdvqtJyz8zRWKZe6QyK51KH9av6VFay2GQvpFrWKHq:
|
||||
Trusted: true
|
||||
ZwxnuL6zMLj4AxJX8Bj369w2tNrVtYxzffVcXZuMxdxbGj:
|
||||
Trusted: true
|
||||
ZwyXdnC8JkC7m796skGD7QWGoYycByR3KVntkXMY8CxRZQ:
|
||||
Trusted: true
|
||||
Zwz7AHiH1EevD9eYFqvQQPbVWyBBcksTRxxafbRx5Cvc4F:
|
||||
Trusted: true
|
||||
ZwzMtc65t9XBMwmLm2xNSL69FvqHGPLiqeNBZ3eEN5a9sS:
|
||||
Trusted: true
|
||||
ZwzjnCUNGsuWnkYmN3QEj8JPLxU6V1QQFk9b47AigmPKiH:
|
||||
Trusted: true
|
17
spn/testing/simple/intel-testnet.json
Normal file
17
spn/testing/simple/intel-testnet.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"BootstrapHubs": [
|
||||
],
|
||||
"TrustedHubs": [
|
||||
"ZwrY9G9HDo1J3qQrrQs8VF2KD99bj7KyWesJ5kWFUDBU6r",
|
||||
"Zwj56ZFXrsud8gc1Rw3zuxRwMLhGkwvtvnTxCVtJ8EWLhQ",
|
||||
"ZwpdW87ityD9i3N9x8oweCJnbZEqo346VBg4mCsCvTr1Zo",
|
||||
"ZwpJ6ebddk1sccUVpo92JUqicBfKzBN2w4pEGoEY7UsNhX",
|
||||
"Zwte3Jffp9PWmeWfrn8RyGuvZZFCg3v7XR3tpQjdo9TpVt",
|
||||
"ZwrTcdiPF5zR5h9q9EdjHCrrXzYVBdQe5HmEYUWXdLkke3",
|
||||
"Zwv7tSn5iU6bYKn53NaGCxPtL8vSxSK7F9VdQezDaDCLBt",
|
||||
"Zwvtdq3K9knP9iNaRS1Ju8CETWTqy7oRwbScjBtJGBpqhB"
|
||||
],
|
||||
"AdviseOnlyTrustedHubs": true,
|
||||
"AdviseOnlyTrustedHomeHubs": true,
|
||||
"AdviseOnlyTrustedDestinationHubs": true
|
||||
}
|
42
spn/testing/simple/join.sh
Executable file
42
spn/testing/simple/join.sh
Executable file
|
@ -0,0 +1,42 @@
|
|||
#!/bin/bash
|
||||
|
||||
cd "$( dirname "${BASH_SOURCE[0]}" )"
|
||||
|
||||
realpath() {
|
||||
path=`eval echo "$1"`
|
||||
folder=$(dirname "$path")
|
||||
echo $(cd "$folder"; pwd)/$(basename "$path");
|
||||
}
|
||||
|
||||
leftover=$(docker ps -a | grep spn-test-simple-me | cut -d" " -f1)
|
||||
if [[ $leftover != "" ]]; then
|
||||
docker stop $leftover
|
||||
docker rm $leftover
|
||||
fi
|
||||
|
||||
if [[ ! -f "../../../cmds/hub/hub" ]]; then
|
||||
echo "please build the hub cmd using cmds/hub/build"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SPN_TEST_BIN="$(realpath ../../../cmds/hub/hub)"
|
||||
SPN_TEST_DATA_DIR="$(realpath ./testdata)"
|
||||
if [[ ! -d "$SPN_TEST_DATA_DIR" ]]; then
|
||||
mkdir "$SPN_TEST_DATA_DIR"
|
||||
fi
|
||||
SPN_TEST_SHARED_DATA_DIR="$(realpath ./testdata/shared)"
|
||||
if [[ ! -d "$SPN_TEST_SHARED_DATA_DIR" ]]; then
|
||||
mkdir "$SPN_TEST_SHARED_DATA_DIR"
|
||||
fi
|
||||
|
||||
docker run -ti \
|
||||
--name spn-test-simple-me \
|
||||
--hostname me \
|
||||
--network spn-test-simple_default \
|
||||
-v $SPN_TEST_BIN:/opt/hub_me:ro \
|
||||
-v $SPN_TEST_DATA_DIR/me:/opt/data \
|
||||
-v $SPN_TEST_SHARED_DATA_DIR:/opt/shared \
|
||||
--entrypoint /opt/hub_me \
|
||||
toolset.safing.network/dev \
|
||||
--devmode --api-address 0.0.0.0:8081 \
|
||||
--data /opt/data -log trace --spn-map test --bootstrap-file /opt/shared/bootstrap.dsd
|
7
spn/testing/simple/reset-databases.sh
Executable file
7
spn/testing/simple/reset-databases.sh
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
cd "$( dirname "${BASH_SOURCE[0]}" )"
|
||||
|
||||
rm -rf testdata/me/*
|
||||
rm -rf testdata/shared/*
|
||||
rm -rf testdata/hub*/databases
|
52
spn/testing/simple/run.sh
Executable file
52
spn/testing/simple/run.sh
Executable file
|
@ -0,0 +1,52 @@
|
|||
#!/bin/bash
|
||||
|
||||
cd "$( dirname "${BASH_SOURCE[0]}" )"
|
||||
|
||||
realpath() {
|
||||
path=`eval echo "$1"`
|
||||
folder=$(dirname "$path")
|
||||
echo $(cd "$folder"; pwd)/$(basename "$path");
|
||||
}
|
||||
|
||||
leftovers=$(docker ps -a | grep spn-test-simple | cut -d" " -f1)
|
||||
if [[ $leftovers != "" ]]; then
|
||||
docker stop $leftovers
|
||||
docker rm $leftovers
|
||||
fi
|
||||
|
||||
if [[ ! -f "../../../cmds/hub/hub" ]]; then
|
||||
echo "please build the hub cmd using cmds/hub/build"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create variables.
|
||||
SPN_TEST_BIN="$(realpath ../../../cmds/hub/hub)"
|
||||
SPN_TEST_DATA_DIR="$(realpath ./testdata)"
|
||||
if [[ ! -d "$SPN_TEST_DATA_DIR" ]]; then
|
||||
mkdir "$SPN_TEST_DATA_DIR"
|
||||
fi
|
||||
SPN_TEST_SHARED_DATA_DIR="$(realpath ./testdata/shared)"
|
||||
if [[ ! -d "$SPN_TEST_SHARED_DATA_DIR" ]]; then
|
||||
mkdir "$SPN_TEST_SHARED_DATA_DIR"
|
||||
fi
|
||||
|
||||
# Check if there is an old binary for testing.
|
||||
SPN_TEST_OLD_BIN=$SPN_TEST_BIN
|
||||
if [[ -f "./testdata/old-hub" ]]; then
|
||||
SPN_TEST_OLD_BIN="$(realpath ./testdata/old-hub)"
|
||||
echo "WARNING: running in hybrid mode with old version at $SPN_TEST_OLD_BIN"
|
||||
fi
|
||||
|
||||
# Export variables
|
||||
export SPN_TEST_BIN
|
||||
export SPN_TEST_OLD_BIN
|
||||
export SPN_TEST_DATA_DIR
|
||||
export SPN_TEST_SHARED_DATA_DIR
|
||||
|
||||
# Copy files.
|
||||
cp config-template.json ./testdata/shared/config-template.json
|
||||
cp entrypoint.sh ./testdata/shared/entrypoint.sh
|
||||
chmod 555 ./testdata/shared/entrypoint.sh
|
||||
|
||||
# Run!
|
||||
docker compose -p spn-test-simple up --remove-orphans
|
15
spn/testing/simple/stop.sh
Executable file
15
spn/testing/simple/stop.sh
Executable file
|
@ -0,0 +1,15 @@
|
|||
#!/bin/bash
|
||||
|
||||
cd "$( dirname "${BASH_SOURCE[0]}" )"
|
||||
|
||||
docker compose -p spn-test-simple stop
|
||||
docker compose -p spn-test-simple rm
|
||||
|
||||
oldnet=$(docker network ls | grep spn-test-simple | cut -d" " -f1)
|
||||
if [[ $oldnet != "" ]]; then
|
||||
docker network rm $oldnet
|
||||
fi
|
||||
|
||||
if [[ -d "data/shared" ]]; then
|
||||
rm -r "data/shared"
|
||||
fi
|
Loading…
Add table
Reference in a new issue