package main
import (
"errors"
"flag"
"fmt"
"os"
"strings"
"syscall"
"egt.run/sf"
"egt.run/sf/mysql"
"golang.org/x/crypto/ssh/terminal"
)
type flags struct {
file string
dry bool
user string
password string
host string
port int
sslKey string
sslCert string
sslCA string
sslServerName string
}
func main() {
if err := run(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
func run() error {
f := parseFlags()
// TODO(egtann) migrate+pledge
// Request database password if not provided as a flag argument
if f.password == "" {
fmt.Printf("%s password: ", f.user)
var err error
password, err := terminal.ReadPassword(int(syscall.Stdin))
if err != nil {
return fmt.Errorf("read pass: %w", err)
}
f.password = string(password)
fmt.Printf("\n")
}
if f.sslKey != "" {
fmt.Println("using tls")
}
db, err := mysql.New(f.user, f.password, f.host, f.port, f.sslKey,
f.sslCert, f.sslCA, f.sslServerName)
if err != nil {
return fmt.Errorf("new db: %w", err)
}
if err := db.Open(); err != nil {
return fmt.Errorf("open db: %w", err)
}
fi, err := os.Open(f.file)
if err != nil {
return fmt.Errorf("open file: %w", err)
}
defer fi.Close()
grants, err := sf.BuildGrants(db, fi)
if err != nil {
return fmt.Errorf("build grants: %w", err)
}
if len(grants) == 0 {
return errors.New("no grants")
}
if f.dry {
fmt.Println(strings.Join(grants, ";\n") + ";")
} else {
if err = sf.ApplyGrants(db, grants); err != nil {
return fmt.Errorf("apply grants: %w", err)
}
}
return nil
}
func parseFlags() *flags {
f := &flags{}
flag.BoolVar(&f.dry, "d", false, "dry run")
flag.StringVar(&f.file, "f", "sf.conf", "config file")
flag.StringVar(&f.user, "u", "root", "user")
flag.StringVar(&f.password, "p", "", "password")
flag.StringVar(&f.host, "H", "127.0.0.1", "host")
flag.IntVar(&f.port, "P", 3306, "port")
flag.StringVar(&f.sslKey, "ssl-key", "", "pem file containing the ssl client key")
flag.StringVar(&f.sslCert, "ssl-cert", "", "pem file containing the ssl client certificate")
flag.StringVar(&f.sslCA, "ssl-ca", "", "pem file containing the ssl server ca")
flag.StringVar(&f.sslServerName, "ssl-server", "", "ssl server name")
flag.Parse()
return f
}