Tighten windows sqlite database permissions (#1769)

This commit is contained in:
blotus 2022-09-28 16:18:00 +02:00 committed by GitHub
parent 52447f6999
commit bfbe180101
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 109 additions and 6 deletions

View file

@ -41,6 +41,7 @@ jobs:
run: |
go install github.com/kyoh86/richgo@v0.3.10
go test -coverprofile coverage.out -covermode=atomic ./... > out.txt
if(!$?) { cat out.txt | sed 's/ *coverage:.*of statements in.*//' | richgo testfilter; Exit 1 }
cat out.txt | sed 's/ *coverage:.*of statements in.*//' | richgo testfilter
- name: Upload unit coverage to Codecov

View file

@ -460,7 +460,12 @@ exclude_regexps: ["\\.gz$"]`
if err != nil {
subLogger.Fatalf("unexpected error: %s", err)
}
expectedLogOutput := "Skipping file test_files/test.log.gz as it matches exclude pattern"
var expectedLogOutput string
if runtime.GOOS == "windows" {
expectedLogOutput = "Skipping file test_files\\test.log.gz as it matches exclude pattern \\.gz"
} else {
expectedLogOutput = "Skipping file test_files/test.log.gz as it matches exclude pattern"
}
if hook.LastEntry() == nil {
t.Fatalf("expected output %s, but got nothing", expectedLogOutput)
}

View file

@ -3,6 +3,7 @@ package kafkaacquisition
import (
"context"
"net"
"runtime"
"strconv"
"testing"
"time"
@ -114,6 +115,9 @@ func createTopic(topic string, broker string) {
}
func TestStreamingAcquisition(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("Skipping test on windows")
}
tests := []struct {
name string
logs []string
@ -181,6 +185,9 @@ topic: crowdsecplaintext`), subLogger)
}
func TestStreamingAcquisitionWithSSL(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("Skipping test on windows")
}
tests := []struct {
name string
logs []string

View file

@ -61,7 +61,6 @@ func NewClient(config *csconfig.DatabaseCfg) (*Client, error) {
entOpt := ent.Log(entLogger.Debug)
switch config.Type {
case "sqlite":
/*if it's the first startup, we want to touch and chmod file*/
if _, err := os.Stat(config.DbPath); os.IsNotExist(err) {
f, err := os.OpenFile(config.DbPath, os.O_CREATE|os.O_RDWR, 0600)
@ -71,10 +70,10 @@ func NewClient(config *csconfig.DatabaseCfg) (*Client, error) {
if err := f.Close(); err != nil {
return &Client{}, errors.Wrapf(err, "failed to create SQLite database file %q", config.DbPath)
}
} else { /*ensure file perms*/
if err := os.Chmod(config.DbPath, 0660); err != nil {
return &Client{}, fmt.Errorf("unable to set perms on %s: %v", config.DbPath, err)
}
//Always try to set permissions to simplify a bit the code for windows (as the permissions set by OpenFile will be garbage)
if err := setFilePerm(config.DbPath, 0600); err != nil {
return &Client{}, fmt.Errorf("unable to set perms on %s: %v", config.DbPath, err)
}
if config.UseWal == nil {
entLogger.Warn("you are using sqlite without WAL, this can have an impact of performance. If you do not store the database in a network share, set db_config.use_wal to true. Set explicitly to false to disable this warning.")

View file

@ -0,0 +1,12 @@
//go:build !windows
package database
import (
"io/fs"
"os"
)
func setFilePerm(path string, mode fs.FileMode) error {
return os.Chmod(path, mode)
}

View file

@ -0,0 +1,79 @@
package database
import (
"fmt"
"io/fs"
log "github.com/sirupsen/logrus"
"golang.org/x/sys/windows"
)
func setFilePerm(path string, mode fs.FileMode) error {
//On windows, we don't care about the mode, just make sure the file is only readable/writable by the owner and group
sd, err := windows.GetNamedSecurityInfo(path, windows.SE_FILE_OBJECT, windows.OWNER_SECURITY_INFORMATION)
if err != nil {
return fmt.Errorf("while getting security info: %w", err)
}
currentOwner, defaulted, err := sd.Owner()
if err != nil {
return fmt.Errorf("while getting owner: %w", err)
}
log.Debugf("current owner is %s (%v) (defaulted: %v)", currentOwner.String(), currentOwner, defaulted)
currentGroup, defaulted, err := sd.Group()
if err != nil {
return fmt.Errorf("while getting group: %w", err)
}
if currentGroup == nil {
log.Debugf("current group is nil (defaulted: %v), using builtin admin instead", defaulted)
currentGroup, err = windows.CreateWellKnownSid(windows.WinBuiltinAdministratorsSid)
if err != nil {
return fmt.Errorf("while creating admin SID: %w", err)
}
}
log.Debugf("current group is %s (%v) (defaulted: %v)", currentGroup.String(), currentGroup, defaulted)
dacl, err := windows.ACLFromEntries(
[]windows.EXPLICIT_ACCESS{
{
AccessPermissions: windows.GENERIC_ALL,
AccessMode: windows.GRANT_ACCESS,
Inheritance: windows.NO_INHERITANCE,
Trustee: windows.TRUSTEE{
MultipleTrusteeOperation: windows.NO_MULTIPLE_TRUSTEE,
TrusteeForm: windows.TRUSTEE_IS_SID,
TrusteeType: windows.TRUSTEE_IS_USER,
TrusteeValue: windows.TrusteeValueFromSID(currentOwner),
},
},
{
AccessPermissions: windows.GENERIC_ALL,
AccessMode: windows.GRANT_ACCESS,
Inheritance: windows.NO_INHERITANCE,
Trustee: windows.TRUSTEE{
MultipleTrusteeOperation: windows.NO_MULTIPLE_TRUSTEE,
TrusteeForm: windows.TRUSTEE_IS_SID,
TrusteeType: windows.TRUSTEE_IS_GROUP,
TrusteeValue: windows.TrusteeValueFromSID(currentGroup),
},
},
}, nil)
if err != nil {
return fmt.Errorf("while creating ACL: %w", err)
}
err = windows.SetNamedSecurityInfo(path, windows.SE_FILE_OBJECT, windows.DACL_SECURITY_INFORMATION|windows.PROTECTED_DACL_SECURITY_INFORMATION, nil, nil, dacl, nil)
if err != nil {
return fmt.Errorf("while setting security info: %w", err)
}
return nil
}