app/vmbackup: prevent password leaks (#3672)

This prevents vmbackup from leaking passwords into logs like shown below.

2023-01-11T15:00:01.050Z        info    VictoriaMetrics/lib/logger/flag.go:12   build version: vmbackup-20221214-211706-tags-v1.85.1-0-g09a70d3e9
2023-01-11T15:00:01.050Z        info    VictoriaMetrics/lib/logger/flag.go:13   command-line flags
2023-01-11T15:00:01.050Z        info    VictoriaMetrics/lib/logger/flag.go:20     -dst="fs:///vm-backups/latest"
2023-01-11T15:00:01.050Z        info    VictoriaMetrics/lib/logger/flag.go:20     -snapshot.createURL="http://user:super_sercret123@victoriametricspshot/create"
2023-01-11T15:00:01.050Z        info    VictoriaMetrics/lib/logger/flag.go:20     -storageDataPath="/storage"
2023-01-11T15:00:01.050Z        info    VictoriaMetrics/app/vmbackup/main.go:53 Snapshot create url http://user:super_sercret123@victoriametrics:8428/snapshot/create
2023-01-11T15:00:01.050Z        info    VictoriaMetrics/app/vmbackup/main.go:60 Snapshot delete url http://user:super_sercret123@victoriametrics:8428/snapshot/delete
This commit is contained in:
Tobias Jungel 2023-01-18 20:35:21 +01:00 committed by GitHub
parent e867df5ef5
commit 777038fe44
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 20 additions and 8 deletions

View file

@ -3,6 +3,7 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"net/url"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@ -41,25 +42,36 @@ func main() {
// Write flags and help message to stdout, since it is easier to grep or pipe. // Write flags and help message to stdout, since it is easier to grep or pipe.
flag.CommandLine.SetOutput(os.Stdout) flag.CommandLine.SetOutput(os.Stdout)
flag.Usage = usage flag.Usage = usage
flagutil.RegisterSecretFlag("snapshot.createURL")
flagutil.RegisterSecretFlag("snapshot.deleteURL")
envflag.Parse() envflag.Parse()
buildinfo.Init() buildinfo.Init()
logger.Init() logger.Init()
pushmetrics.Init() pushmetrics.Init()
if len(*snapshotCreateURL) > 0 { if len(*snapshotCreateURL) > 0 {
// create net/url object
createUrl, err := url.Parse(*snapshotCreateURL)
if err != nil {
logger.Fatalf("cannot parse snapshotCreateURL: %s", err)
}
if len(*snapshotName) > 0 { if len(*snapshotName) > 0 {
logger.Fatalf("-snapshotName shouldn't be set if -snapshot.createURL is set, since snapshots are created automatically in this case") logger.Fatalf("-snapshotName shouldn't be set if -snapshot.createURL is set, since snapshots are created automatically in this case")
} }
logger.Infof("Snapshot create url %s", *snapshotCreateURL) logger.Infof("Snapshot create url %s", createUrl.Redacted())
if len(*snapshotDeleteURL) <= 0 { if len(*snapshotDeleteURL) <= 0 {
err := flag.Set("snapshot.deleteURL", strings.Replace(*snapshotCreateURL, "/create", "/delete", 1)) err := flag.Set("snapshot.deleteURL", strings.Replace(*snapshotCreateURL, "/create", "/delete", 1))
if err != nil { if err != nil {
logger.Fatalf("Failed to set snapshot.deleteURL flag: %v", err) logger.Fatalf("Failed to set snapshot.deleteURL flag: %v", err)
} }
} }
logger.Infof("Snapshot delete url %s", *snapshotDeleteURL) deleteUrl, err := url.Parse(*snapshotCreateURL)
if err != nil {
logger.Fatalf("cannot parse snapshotDeleteURL: %s", err)
}
logger.Infof("Snapshot delete url %s", deleteUrl.Redacted())
name, err := snapshot.Create(*snapshotCreateURL) name, err := snapshot.Create(createUrl.String())
if err != nil { if err != nil {
logger.Fatalf("cannot create snapshot: %s", err) logger.Fatalf("cannot create snapshot: %s", err)
} }
@ -69,7 +81,7 @@ func main() {
} }
defer func() { defer func() {
err := snapshot.Delete(*snapshotDeleteURL, name) err := snapshot.Delete(deleteUrl.String(), name)
if err != nil { if err != nil {
logger.Fatalf("cannot delete snapshot: %s", err) logger.Fatalf("cannot delete snapshot: %s", err)
} }

View file

@ -39,13 +39,13 @@ func Create(createSnapshotURL string) (string, error) {
return "", err return "", err
} }
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("unexpected status code returned from %q: %d; expecting %d; response body: %q", createSnapshotURL, resp.StatusCode, http.StatusOK, body) return "", fmt.Errorf("unexpected status code returned from %q: %d; expecting %d; response body: %q", u.Redacted(), resp.StatusCode, http.StatusOK, body)
} }
snap := snapshot{} snap := snapshot{}
err = json.Unmarshal(body, &snap) err = json.Unmarshal(body, &snap)
if err != nil { if err != nil {
return "", fmt.Errorf("cannot parse JSON response from %q: %w; response body: %q", createSnapshotURL, err, body) return "", fmt.Errorf("cannot parse JSON response from %q: %w; response body: %q", u.Redacted(), err, body)
} }
if snap.Status == "ok" { if snap.Status == "ok" {
@ -77,13 +77,13 @@ func Delete(deleteSnapshotURL string, snapshotName string) error {
return err return err
} }
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
return fmt.Errorf("unexpected status code returned from %q: %d; expecting %d; response body: %q", deleteSnapshotURL, resp.StatusCode, http.StatusOK, body) return fmt.Errorf("unexpected status code returned from %q: %d; expecting %d; response body: %q", u.Redacted(), resp.StatusCode, http.StatusOK, body)
} }
snap := snapshot{} snap := snapshot{}
err = json.Unmarshal(body, &snap) err = json.Unmarshal(body, &snap)
if err != nil { if err != nil {
return fmt.Errorf("cannot parse JSON response from %q: %w; response body: %q", deleteSnapshotURL, err, body) return fmt.Errorf("cannot parse JSON response from %q: %w; response body: %q", u.Redacted(), err, body)
} }
if snap.Status == "ok" { if snap.Status == "ok" {