switch utils commands to basic auth, remove secret passing

This commit is contained in:
Umputun
2018-12-30 18:00:32 -06:00
parent 4215db8d89
commit 80467c39af
9 changed files with 52 additions and 44 deletions
+8 -6
View File
@@ -15,17 +15,18 @@ import (
// BackupCommand set of flags and command for export
// ExportPath used as a separate element to leverage BACKUP_PATH. If ExportFile has a path (i.e. with /) BACKUP_PATH ignored.
type BackupCommand struct {
ExportPath string `short:"p" long:"path" env:"BACKUP_PATH" default:"./var/backup" description:"export path"`
ExportFile string `short:"f" long:"file" default:"userbackup-{{.SITE}}-{{.TS}}.gz" description:"file name"`
Site string `short:"s" long:"site" env:"SITE" default:"remark" description:"site name"`
Timeout time.Duration `long:"timeout" default:"15m" description:"export (backup) timeout"`
ExportPath string `short:"p" long:"path" env:"BACKUP_PATH" default:"./var/backup" description:"export path"`
ExportFile string `short:"f" long:"file" default:"userbackup-{{.SITE}}-{{.TS}}.gz" description:"file name"`
Site string `short:"s" long:"site" env:"SITE" default:"remark" description:"site name"`
Timeout time.Duration `long:"timeout" default:"15m" description:"export (backup) timeout"`
AdminPasswd string `long:"admin-passwd" env:"ADMIN_PASSWD" required:"true" description:"admin basic auth password"`
CommonOpts
}
// Execute runs export with ExportCommand parameters, entry point for "export" command
func (ec *BackupCommand) Execute(args []string) error {
log.Printf("[INFO] export to %s, site %s", ec.ExportPath, ec.Site)
resetEnv("SECRET")
resetEnv("SECRET", "ADMIN_PASSWD")
fp := fileParser{site: ec.Site, path: ec.ExportPath, file: ec.ExportFile}
fname, err := fp.parse(time.Now())
@@ -39,11 +40,12 @@ func (ec *BackupCommand) Execute(args []string) error {
client := http.Client{}
ctx, cancel := context.WithTimeout(context.Background(), ec.Timeout)
defer cancel()
exportURL := fmt.Sprintf("%s/api/v1/admin/export?mode=file&site=%s&secret=%s", ec.RemarkURL, ec.Site, ec.SharedSecret)
exportURL := fmt.Sprintf("%s/api/v1/admin/export?mode=file&site=%s", ec.RemarkURL, ec.Site)
req, err := http.NewRequest(http.MethodGet, exportURL, nil)
if err != nil {
return errors.Wrapf(err, "can't make export request for %s", exportURL)
}
req.SetBasicAuth("admin", ec.AdminPasswd)
// get with timeout
resp, err := client.Do(req.WithContext(ctx))
+5 -4
View File
@@ -8,7 +8,7 @@ import (
"os"
"testing"
"github.com/jessevdk/go-flags"
flags "github.com/jessevdk/go-flags"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -24,7 +24,7 @@ func TestBackup_Execute(t *testing.T) {
cmd := BackupCommand{}
cmd.SetCommon(CommonOpts{RemarkURL: ts.URL, SharedSecret: "123456"})
p := flags.NewParser(&cmd, flags.Default)
_, err := p.ParseArgs([]string{"--site=remark", "--path=/tmp", "--file={{.SITE}}-test.export"})
_, err := p.ParseArgs([]string{"--site=remark", "--path=/tmp", "--file={{.SITE}}-test.export", "--admin-passwd=secret"})
require.Nil(t, err)
err = cmd.Execute(nil)
assert.NoError(t, err)
@@ -48,7 +48,7 @@ func TestBackup_ExecuteFailedStatus(t *testing.T) {
cmd.SetCommon(CommonOpts{RemarkURL: ts.URL, SharedSecret: "123456"})
p := flags.NewParser(&cmd, flags.Default)
_, err := p.ParseArgs([]string{"--site=remark", "--path=/tmp", "--file={{.SITE}}-test.export"})
_, err := p.ParseArgs([]string{"--site=remark", "--path=/tmp", "--file={{.SITE}}-test.export", "--admin-passwd=secret"})
require.Nil(t, err)
err = cmd.Execute(nil)
assert.EqualError(t, err, `error response "400 Bad Request", some error`)
@@ -66,7 +66,8 @@ func TestBackup_ExecuteFailedWrite(t *testing.T) {
cmd.SetCommon(CommonOpts{RemarkURL: ts.URL, SharedSecret: "123456"})
p := flags.NewParser(&cmd, flags.Default)
_, err := p.ParseArgs([]string{"--site=remark", "--path=/tmp", "--file=/tmp/no-such-dir/{{.SITE}}-test.export"})
_, err := p.ParseArgs([]string{"--site=remark", "--path=/tmp",
"--file=/tmp/no-such-dir/{{.SITE}}-test.export", "--admin-passwd=secret"})
require.Nil(t, err)
err = cmd.Execute(nil)
assert.EqualError(t, err, `can't create backup file /tmp/no-such-dir/remark-test.export: open /tmp/no-such-dir/remark-test.export: no such file or directory`)
+10 -8
View File
@@ -15,12 +15,13 @@ import (
// CleanupCommand set of flags and command for cleanup
type CleanupCommand struct {
Site string `short:"s" long:"site" env:"SITE" default:"remark" description:"site name"`
Dry bool `long:"dry" description:"dry mode, will not remove comments"`
From string `long:"from" description:"from yyyymmdd"`
To string `long:"to" description:"from yyyymmdd"`
BadWords []string `short:"w" long:"bword" description:"bad word(s)"`
BadUsers []string `short:"u" long:"buser" description:"bad user(s)"`
Site string `short:"s" long:"site" env:"SITE" default:"remark" description:"site name"`
Dry bool `long:"dry" description:"dry mode, will not remove comments"`
From string `long:"from" description:"from yyyymmdd"`
To string `long:"to" description:"from yyyymmdd"`
BadWords []string `short:"w" long:"bword" description:"bad word(s)"`
BadUsers []string `short:"u" long:"buser" description:"bad user(s)"`
AdminPasswd string `long:"admin-passwd" env:"ADMIN_PASSWD" required:"true" description:"admin basic auth password"`
CommonOpts
}
@@ -160,12 +161,13 @@ func (cc *CleanupCommand) listComments(postURL string) ([]store.Comment, error)
// deleteComment with DELETE /admin/comment/{id}?site=siteID&url=post-url
func (cc *CleanupCommand) deleteComment(c store.Comment) error {
deleteURL := fmt.Sprintf("%s/api/v1/admin/comment/%s?site=%s&url=%s&format=plain&secret=%s",
cc.RemarkURL, c.ID, cc.Site, c.Locator.URL, cc.SharedSecret)
deleteURL := fmt.Sprintf("%s/api/v1/admin/comment/%s?site=%s&url=%s&format=plain", cc.RemarkURL, c.ID, cc.Site, c.Locator.URL)
req, err := http.NewRequest("DELETE", deleteURL, nil)
if err != nil {
return errors.Wrapf(err, "failed to make delete request for comment %s, %s", c.ID, c.Locator.URL)
}
req.SetBasicAuth("admin", cc.AdminPasswd)
client := http.Client{}
r, err := client.Do(req)
if err != nil {
+3 -3
View File
@@ -67,7 +67,7 @@ func TestCleanup_postsInRange(t *testing.T) {
cmd := CleanupCommand{}
cmd.SetCommon(CommonOpts{RemarkURL: ts.URL, SharedSecret: "123456"})
p := flags.NewParser(&cmd, flags.Default)
_, err := p.ParseArgs([]string{"--site=remark", "--bword=bad1", "--bword=bad2", "--buser=bu_"})
_, err := p.ParseArgs([]string{"--site=remark", "--bword=bad1", "--bword=bad2", "--buser=bu_", "--admin-passwd=secret"})
require.Nil(t, err)
posts, err := cmd.postsInRange("20181218", "20181219")
assert.NoError(t, err)
@@ -90,7 +90,7 @@ func TestCleanup_listComments(t *testing.T) {
cmd := CleanupCommand{}
cmd.SetCommon(CommonOpts{RemarkURL: ts.URL, SharedSecret: "123456"})
p := flags.NewParser(&cmd, flags.Default)
_, err := p.ParseArgs([]string{"--site=remark", "--bword=bad1", "--bword=bad2", "--buser=bu_"})
_, err := p.ParseArgs([]string{"--site=remark", "--bword=bad1", "--bword=bad2", "--buser=bu_", "--admin-passwd=secret"})
require.Nil(t, err)
comments, err := cmd.listComments("http://test.com/post1")
@@ -117,7 +117,7 @@ func TestCleanup_Execute(t *testing.T) {
cmd.SetCommon(CommonOpts{RemarkURL: ts.URL, SharedSecret: "123456"})
p := flags.NewParser(&cmd, flags.Default)
_, err := p.ParseArgs([]string{"--site=remark", "--bword=bad1", "--bword=bad2", "--buser=bu_",
"--from=20181217", "--to=20181218"})
"--from=20181217", "--to=20181218", "--admin-passwd=secret"})
require.Nil(t, err)
err = cmd.Execute(nil)
assert.NoError(t, err)
+8 -7
View File
@@ -17,17 +17,18 @@ import (
// ImportCommand set of flags and command for import
type ImportCommand struct {
InputFile string `short:"f" long:"file" description:"input file name" required:"true"`
Provider string `short:"p" long:"provider" default:"disqus" choice:"disqus" choice:"wordpress" description:"import format"`
Site string `short:"s" long:"site" env:"SITE" default:"remark" description:"site name"`
Timeout time.Duration `long:"timeout" default:"15m" description:"import timeout"`
InputFile string `short:"f" long:"file" description:"input file name" required:"true"`
Provider string `short:"p" long:"provider" default:"disqus" choice:"disqus" choice:"wordpress" description:"import format"`
Site string `short:"s" long:"site" env:"SITE" default:"remark" description:"site name"`
Timeout time.Duration `long:"timeout" default:"15m" description:"import timeout"`
AdminPasswd string `long:"admin-passwd" env:"ADMIN_PASSWD" required:"true" description:"admin basic auth password"`
CommonOpts
}
// Execute runs import with ImportCommand parameters, entry point for "import" command
func (ic *ImportCommand) Execute(args []string) error {
log.Printf("[INFO] import %s (%s), site %s", ic.InputFile, ic.Provider, ic.Site)
resetEnv("SECRET")
resetEnv("SECRET", "ADMIN_PASSWD")
reader, err := ic.reader(ic.InputFile)
if err != nil {
@@ -37,12 +38,12 @@ func (ic *ImportCommand) Execute(args []string) error {
client := http.Client{}
ctx, cancel := context.WithTimeout(context.Background(), ic.Timeout)
defer cancel()
importURL := fmt.Sprintf("%s/api/v1/admin/import?site=%s&provider=%s&secret=%s",
ic.RemarkURL, ic.Site, ic.Provider, ic.SharedSecret)
importURL := fmt.Sprintf("%s/api/v1/admin/import?site=%s&provider=%s", ic.RemarkURL, ic.Site, ic.Provider)
req, err := http.NewRequest(http.MethodPost, importURL, reader)
if err != nil {
return errors.Wrapf(err, "can't make import request for %s", importURL)
}
req.SetBasicAuth("admin", ic.AdminPasswd)
resp, err := client.Do(req.WithContext(ctx)) // closes request's reader
if err != nil {
+6 -6
View File
@@ -33,7 +33,7 @@ func TestImport_Execute(t *testing.T) {
cmd.SetCommon(CommonOpts{RemarkURL: ts.URL, SharedSecret: "123456"})
p := flags.NewParser(&cmd, flags.Default)
_, err := p.ParseArgs([]string{"--site=remark", "--file=testdata/import.txt"})
_, err := p.ParseArgs([]string{"--site=remark", "--file=testdata/import.txt", "--admin-passwd=secret"})
require.Nil(t, err)
err = cmd.Execute(nil)
assert.NoError(t, err)
@@ -42,7 +42,7 @@ func TestImport_Execute(t *testing.T) {
cmd.SetCommon(CommonOpts{RemarkURL: ts.URL, SharedSecret: "123456"})
p = flags.NewParser(&cmd, flags.Default)
_, err = p.ParseArgs([]string{"--site=remark", "--file=testdata/import.txt.gz"})
_, err = p.ParseArgs([]string{"--site=remark", "--file=testdata/import.txt.gz", "--admin-passwd=secret"})
require.Nil(t, err)
err = cmd.Execute(nil)
assert.NoError(t, err)
@@ -60,7 +60,7 @@ func TestImport_ExecuteFailed(t *testing.T) {
cmd := ImportCommand{}
cmd.SetCommon(CommonOpts{RemarkURL: ts.URL, SharedSecret: "123456"})
p := flags.NewParser(&cmd, flags.Default)
_, err := p.ParseArgs([]string{"--site=remark", "--file=testdata/import-no.txt"})
_, err := p.ParseArgs([]string{"--site=remark", "--file=testdata/import-no.txt", "--admin-passwd=secret"})
require.Nil(t, err)
err = cmd.Execute(nil)
t.Log(err)
@@ -70,7 +70,7 @@ func TestImport_ExecuteFailed(t *testing.T) {
cmd = ImportCommand{}
cmd.SetCommon(CommonOpts{RemarkURL: "http://127.0.0.1:12345", SharedSecret: "123456"})
p = flags.NewParser(&cmd, flags.Default)
_, err = p.ParseArgs([]string{"--site=remark", "--file=testdata/import.txt"})
_, err = p.ParseArgs([]string{"--site=remark", "--file=testdata/import.txt", "--admin-passwd=secret"})
require.Nil(t, err)
err = cmd.Execute(nil)
t.Log(err)
@@ -86,7 +86,7 @@ func TestImport_ExecuteFailed(t *testing.T) {
cmd = ImportCommand{}
cmd.SetCommon(CommonOpts{RemarkURL: ts2.URL, SharedSecret: "123456"})
p = flags.NewParser(&cmd, flags.Default)
_, err = p.ParseArgs([]string{"--site=remark", "--file=testdata/import.txt"})
_, err = p.ParseArgs([]string{"--site=remark", "--file=testdata/import.txt", "--admin-passwd=secret"})
require.Nil(t, err)
err = cmd.Execute(nil)
t.Log(err)
@@ -111,7 +111,7 @@ func TestImport_ExecuteTimeout(t *testing.T) {
cmd.SetCommon(CommonOpts{RemarkURL: ts.URL, SharedSecret: "123456"})
p := flags.NewParser(&cmd, flags.Default)
_, err := p.ParseArgs([]string{"--site=remark", "--file=testdata/import.txt", "--timeout=300ms"})
_, err := p.ParseArgs([]string{"--site=remark", "--file=testdata/import.txt", "--timeout=300ms", "--admin-passwd=secret"})
require.Nil(t, err)
err = cmd.Execute(nil)
assert.NotNil(t, err)
+10 -8
View File
@@ -10,8 +10,9 @@ type RestoreCommand struct {
ImportPath string `short:"p" long:"path" env:"BACKUP_PATH" default:"./var/backup" description:"export path"`
ImportFile string `short:"f" long:"file" default:"userbackup-{{.SITE}}-{{.YYYYMMDD}}.gz" description:"file name" required:"true"`
Site string `short:"s" long:"site" env:"SITE" default:"remark" description:"site name"`
Timeout time.Duration `long:"timeout" default:"15m" description:"import timeout"`
Site string `short:"s" long:"site" env:"SITE" default:"remark" description:"site name"`
Timeout time.Duration `long:"timeout" default:"15m" description:"import timeout"`
AdminPasswd string `long:"admin-passwd" env:"ADMIN_PASSWD" required:"true" description:"admin basic auth password"`
CommonOpts
}
@@ -19,7 +20,7 @@ type RestoreCommand struct {
// uses ImportCommand with constructed full file name
func (rc *RestoreCommand) Execute(args []string) error {
log.Printf("[INFO] restore %s, site %s", rc.ImportFile, rc.Site)
resetEnv("SECRET")
resetEnv("SECRET", "ADMIN_PASSWD")
fp := fileParser{site: rc.Site, path: rc.ImportPath, file: rc.ImportFile}
fname, err := fp.parse(time.Now())
@@ -27,11 +28,12 @@ func (rc *RestoreCommand) Execute(args []string) error {
return err
}
importer := ImportCommand{
InputFile: fname,
Site: rc.Site,
Provider: "native",
Timeout: rc.Timeout,
CommonOpts: rc.CommonOpts,
InputFile: fname,
Site: rc.Site,
Provider: "native",
Timeout: rc.Timeout,
AdminPasswd: rc.AdminPasswd,
CommonOpts: rc.CommonOpts,
}
return importer.Execute(args)
}
+1 -1
View File
@@ -31,7 +31,7 @@ func TestRestore_Execute(t *testing.T) {
cmd.SetCommon(CommonOpts{RemarkURL: ts.URL, SharedSecret: "123456"})
p := flags.NewParser(&cmd, flags.Default)
_, err := p.ParseArgs([]string{"--site=remark", "--path=testdata", "--file=import.txt"})
_, err := p.ParseArgs([]string{"--site=remark", "--path=testdata", "--file=import.txt", "--admin-passwd=secret"})
require.Nil(t, err)
err = cmd.Execute(nil)
assert.NoError(t, err)
+1 -1
View File
@@ -161,7 +161,7 @@ type serverApp struct {
// Execute is the entry point for "server" command, called by flag parser
func (s *ServerCommand) Execute(args []string) error {
log.Printf("[INFO] start server on port %d", s.Port)
resetEnv("SECRET", "AUTH_GOOGLE_CSEC", "AUTH_GITHUB_CSEC", "AUTH_FACEBOOK_CSEC", "AUTH_YANDEX_CSEC")
resetEnv("SECRET", "AUTH_GOOGLE_CSEC", "AUTH_GITHUB_CSEC", "AUTH_FACEBOOK_CSEC", "AUTH_YANDEX_CSEC", "ADMIN_PASSWD")
ctx, cancel := context.WithCancel(context.Background())
go func() { // catch signal and invoke graceful termination