rclone config redacted: implement support mechanism for showing redacted config

This introduces a new fs.Option flag, Sensitive and uses this along
with IsPassword to redact the info in the config file for support
purposes.

It adds this flag into backends where appropriate. It was necessary to
add oauthutil.SharedOptions to some backends as they were missing
them.

Fixes #5209
This commit is contained in:
Nick Craig-Wood
2023-07-06 17:55:53 +01:00
parent 297f15a3e3
commit d0d41fe847
41 changed files with 407 additions and 227 deletions

View File

@@ -302,19 +302,41 @@ func mustFindByName(name string) *fs.RegInfo {
return fs.MustFind(fsType)
}
// findByName finds the RegInfo for the remote name passed in or
// returns an error
func findByName(name string) (*fs.RegInfo, error) {
fsType := FileGet(name, "type")
if fsType == "" {
return nil, fmt.Errorf("couldn't find type of fs for %q", name)
}
return fs.Find(fsType)
}
// printRemoteOptions prints the options of the remote
func printRemoteOptions(name string, prefix string, sep string) {
fs := mustFindByName(name)
func printRemoteOptions(name string, prefix string, sep string, redacted bool) {
fsInfo, err := findByName(name)
if err != nil {
fmt.Printf("# %v\n", err)
fsInfo = nil
}
for _, key := range LoadedData().GetKeyList(name) {
isPassword := false
for _, option := range fs.Options {
if option.Name == key && option.IsPassword {
isPassword = true
break
isSensitive := false
if fsInfo != nil {
for _, option := range fsInfo.Options {
if option.Name == key {
if option.IsPassword {
isPassword = true
} else if option.Sensitive {
isSensitive = true
}
}
}
}
value := FileGet(name, key)
if isPassword && value != "" {
if redacted && (isSensitive || isPassword) && value != "" {
fmt.Printf("%s%s%sXXX\n", prefix, key, sep)
} else if isPassword && value != "" {
fmt.Printf("%s%s%s*** ENCRYPTED ***\n", prefix, key, sep)
} else {
fmt.Printf("%s%s%s%s\n", prefix, key, sep, value)
@@ -324,13 +346,19 @@ func printRemoteOptions(name string, prefix string, sep string) {
// listRemoteOptions lists the options of the remote
func listRemoteOptions(name string) {
printRemoteOptions(name, "- ", ": ")
printRemoteOptions(name, "- ", ": ", false)
}
// ShowRemote shows the contents of the remote in config file format
func ShowRemote(name string) {
fmt.Printf("[%s]\n", name)
printRemoteOptions(name, "", " = ")
printRemoteOptions(name, "", " = ", false)
}
// ShowRedactedRemote shows the contents of the remote in config file format
func ShowRedactedRemote(name string) {
fmt.Printf("[%s]\n", name)
printRemoteOptions(name, "", " = ", true)
}
// OkRemote prints the contents of the remote and ask if it is OK
@@ -634,6 +662,22 @@ func ShowConfig() {
fmt.Printf("%s", str)
}
// ShowRedactedConfig prints the redacted (unencrypted) config options
func ShowRedactedConfig() {
remotes := LoadedData().GetSectionList()
if len(remotes) == 0 {
fmt.Println("; empty config")
return
}
sort.Strings(remotes)
for i, remote := range remotes {
if i != 0 {
fmt.Println()
}
ShowRedactedRemote(remote)
}
}
// EditConfig edits the config file interactively
func EditConfig(ctx context.Context) (err error) {
for {