feat: Dodane parsowanie pliku pgpass
pgpass jest prsowany i przy uruchomieniu psql podawane jest wybrane hasło pasujące do połaczenia
This commit is contained in:
parent
c34954ef14
commit
7d9c3d8f62
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
|
/.vscode
|
||||||
/output
|
/output
|
||||||
/pgpass
|
/pgpass
|
||||||
|
|
||||||
|
12
mgr/mgr.go
12
mgr/mgr.go
@ -9,6 +9,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"baal.ar76.eu/x/pub/multisql/cfg"
|
"baal.ar76.eu/x/pub/multisql/cfg"
|
||||||
|
"baal.ar76.eu/x/pub/multisql/pass"
|
||||||
"baal.ar76.eu/x/pub/multisql/psql"
|
"baal.ar76.eu/x/pub/multisql/psql"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -69,6 +70,15 @@ func (self Manager) Run() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var passdb *pass.PassDb
|
||||||
|
|
||||||
|
if self.config.PassFile != "" {
|
||||||
|
passdb, err = pass.Load(self.config.PassFile, "TODO")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var group sync.WaitGroup
|
var group sync.WaitGroup
|
||||||
|
|
||||||
for _, con := range self.config.Connections {
|
for _, con := range self.config.Connections {
|
||||||
@ -84,7 +94,7 @@ func (self Manager) Run() error {
|
|||||||
go self.Logger(&group, stream, con)
|
go self.Logger(&group, stream, con)
|
||||||
|
|
||||||
sql := psql.Create(
|
sql := psql.Create(
|
||||||
self.config.PassFile,
|
passdb,
|
||||||
dbDir,
|
dbDir,
|
||||||
scripts,
|
scripts,
|
||||||
con,
|
con,
|
||||||
|
81
pass/pass.go
Normal file
81
pass/pass.go
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
package pass
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
type pgpassrow struct {
|
||||||
|
hostname string
|
||||||
|
port string
|
||||||
|
database string
|
||||||
|
username string
|
||||||
|
password string
|
||||||
|
}
|
||||||
|
|
||||||
|
type PassDb struct {
|
||||||
|
db []pgpassrow
|
||||||
|
cache map[string]*pgpassrow
|
||||||
|
}
|
||||||
|
|
||||||
|
func Load(file string, master string) (*PassDb, error) {
|
||||||
|
|
||||||
|
data, err := os.ReadFile(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
lines := bytes.Split(data, []byte{'\n'})
|
||||||
|
|
||||||
|
var rows []pgpassrow
|
||||||
|
|
||||||
|
for i, line := range lines {
|
||||||
|
line = bytes.TrimRight(line, "\n\r \t")
|
||||||
|
if len(line) == 0 || line[0] == byte('#') {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fields := bytes.Split(line, []byte{':'})
|
||||||
|
if len(fields) != 5 {
|
||||||
|
return nil, fmt.Errorf("błąd w pliku hasłeł %s:%d: niewłaściwa liczba pól", file, i)
|
||||||
|
}
|
||||||
|
rows = append(rows, pgpassrow{
|
||||||
|
hostname: string(fields[0]),
|
||||||
|
port: string(fields[1]),
|
||||||
|
database: string(fields[2]),
|
||||||
|
username: string(fields[3]),
|
||||||
|
password: string(fields[4]),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return &PassDb{
|
||||||
|
db: rows,
|
||||||
|
cache: make(map[string]*pgpassrow),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func match(value string, pattern string) bool {
|
||||||
|
return pattern == "*" || pattern == value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *PassDb) FindPassword(host string, port uint, database string, user string) string {
|
||||||
|
myport := fmt.Sprintf("%d", port)
|
||||||
|
key := fmt.Sprintf("%s:%s:%s:%s", host, myport, database, user)
|
||||||
|
cached, ok := self.cache[key]
|
||||||
|
if ok {
|
||||||
|
return cached.password
|
||||||
|
}
|
||||||
|
|
||||||
|
// pierwszy pasujący do wzorca
|
||||||
|
for i := range self.db {
|
||||||
|
if match(host, self.db[i].hostname) &&
|
||||||
|
match(myport, self.db[i].port) &&
|
||||||
|
match(database, self.db[i].database) &&
|
||||||
|
match(user, self.db[i].username) {
|
||||||
|
|
||||||
|
self.cache[key] = &self.db[i]
|
||||||
|
return self.db[i].password
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
51
psql/psql.go
51
psql/psql.go
@ -10,15 +10,16 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"baal.ar76.eu/x/pub/multisql/cfg"
|
"baal.ar76.eu/x/pub/multisql/cfg"
|
||||||
|
"baal.ar76.eu/x/pub/multisql/pass"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Instance struct {
|
type Instance struct {
|
||||||
outdir string
|
outdir string
|
||||||
scripts []string
|
scripts []string
|
||||||
passfile string
|
pasdb *pass.PassDb
|
||||||
psqlExe string
|
psqlExe string
|
||||||
conn cfg.Connection
|
conn cfg.Connection
|
||||||
verbose bool
|
verbose bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Result struct {
|
type Result struct {
|
||||||
@ -26,32 +27,22 @@ type Result struct {
|
|||||||
Err error
|
Err error
|
||||||
}
|
}
|
||||||
|
|
||||||
func Create(passfile string, outdir string, scripts []string, conn cfg.Connection, psqlExe string, verbose bool) (instnace Instance) {
|
func Create(passdb *pass.PassDb, outdir string, scripts []string, conn cfg.Connection, psqlExe string, verbose bool) (instnace Instance) {
|
||||||
|
|
||||||
instnace = Instance{
|
instnace = Instance{
|
||||||
outdir: outdir,
|
outdir: outdir,
|
||||||
scripts: scripts,
|
scripts: scripts,
|
||||||
passfile: passfile,
|
pasdb: passdb,
|
||||||
conn: conn,
|
conn: conn,
|
||||||
psqlExe: psqlExe,
|
psqlExe: psqlExe,
|
||||||
verbose: verbose,
|
verbose: verbose,
|
||||||
}
|
}
|
||||||
return instnace
|
return instnace
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Instance) Exec(result chan<- Result) {
|
func (self Instance) Exec(result chan<- Result) {
|
||||||
absPassFile := ""
|
|
||||||
if self.passfile != "" {
|
|
||||||
var err error
|
|
||||||
absPassFile, err = filepath.Abs(self.passfile)
|
|
||||||
if err != nil {
|
|
||||||
result <- Result{
|
|
||||||
Script: "*",
|
|
||||||
Err: fmt.Errorf("problem ze zbudowaniem ściężki do pliku haseł: %w", err),
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
connString := fmt.Sprintf("host=%s port=%d dbname=%s user=%s", self.conn.Host, self.conn.Port, self.conn.DbName, self.conn.User)
|
connString := fmt.Sprintf("host=%s port=%d dbname=%s user=%s", self.conn.Host, self.conn.Port, self.conn.DbName, self.conn.User)
|
||||||
|
|
||||||
for _, scr := range self.scripts {
|
for _, scr := range self.scripts {
|
||||||
@ -65,7 +56,8 @@ func (self Instance) Exec(result chan<- Result) {
|
|||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
err = self.cmdPsql(outdir, connString, scr, absPassFile)
|
password := self.pasdb.FindPassword(self.conn.Host, self.conn.Port, self.conn.DbName, self.conn.User)
|
||||||
|
err = self.cmdPsql(outdir, connString, scr, password)
|
||||||
result <- Result{
|
result <- Result{
|
||||||
Script: scr,
|
Script: scr,
|
||||||
Err: err,
|
Err: err,
|
||||||
@ -74,7 +66,7 @@ func (self Instance) Exec(result chan<- Result) {
|
|||||||
close(result)
|
close(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Instance) cmdPsql(outdir string, connString string, script string, passfile string) error {
|
func (self Instance) cmdPsql(outdir string, connString string, script string, password string) error {
|
||||||
absScript, err := filepath.Abs(script)
|
absScript, err := filepath.Abs(script)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("problem ze zbudowaniem ściezki do skryptu: %w", err)
|
return fmt.Errorf("problem ze zbudowaniem ściezki do skryptu: %w", err)
|
||||||
@ -112,13 +104,12 @@ func (self Instance) cmdPsql(outdir string, connString string, script string, pa
|
|||||||
cmd.Stdout = fhOut
|
cmd.Stdout = fhOut
|
||||||
cmd.Dir = outdir
|
cmd.Dir = outdir
|
||||||
|
|
||||||
if passfile != "" {
|
if password != "" {
|
||||||
env := os.Environ()
|
env := os.Environ()
|
||||||
env = append(env, "PGPASSFILE=" + passfile)
|
env = append(env, "PGPASSWORD="+password)
|
||||||
cmd.Env = env
|
cmd.Env = env
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if self.verbose {
|
if self.verbose {
|
||||||
log.Printf("Uruchamiam %s", cmd.String())
|
log.Printf("Uruchamiam %s", cmd.String())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user