lockbox

password manager
Log | Files | Refs | README | LICENSE

commit 738a63269c55a9204a20e7125a3e9dc5dcbf35a7
parent 58a0c851a9cf6d5c61b3e60c42aa9e62ae33d339
Author: Sean Enck <sean@ttypty.com>
Date:   Sun,  3 Sep 2023 20:04:52 -0400

key should be calculated, not a re-used field

Diffstat:
Minternal/config/core.go | 32++++++++++++++++++--------------
Minternal/config/vars.go | 97+++++++++++++++++++++++++++++++++++++++----------------------------------------
2 files changed, 66 insertions(+), 63 deletions(-)

diff --git a/internal/config/core.go b/internal/config/core.go @@ -54,7 +54,7 @@ type ( // SystemPlatform represents the platform lockbox is running on. SystemPlatform string environmentBase struct { - key string + subKey string desc string requirement string whenUnset string @@ -125,9 +125,13 @@ func environOrDefault(envKey, defaultValue string) string { return val } +func (e environmentBase) key() string { + return fmt.Sprintf("LOCKBOX_%s", e.subKey) +} + // Get will get the boolean value for the setting func (e EnvironmentBool) Get() (bool, error) { - read := strings.ToLower(strings.TrimSpace(getExpand(e.key))) + read := strings.ToLower(strings.TrimSpace(getExpand(e.key()))) switch read { case no: return false, nil @@ -137,13 +141,13 @@ func (e EnvironmentBool) Get() (bool, error) { return e.defaultValue, nil } - return false, fmt.Errorf("invalid yes/no env value for %s", e.key) + return false, fmt.Errorf("invalid yes/no env value for %s", e.key()) } // Get will get the integer value for the setting func (e EnvironmentInt) Get() (int, error) { val := e.defaultValue - use := getExpand(e.key) + use := getExpand(e.key()) if use != "" { i, err := strconv.Atoi(use) if err != nil { @@ -171,14 +175,14 @@ func (e EnvironmentInt) Get() (int, error) { // Get will read the string from the environment func (e EnvironmentString) Get() string { if !e.canDefault { - return getExpand(e.key) + return getExpand(e.key()) } - return environOrDefault(e.key, e.defaultValue) + return environOrDefault(e.key(), e.defaultValue) } // Get will read (and shlex) the value if set func (e EnvironmentCommand) Get() ([]string, error) { - value := environOrDefault(e.key, "") + value := environOrDefault(e.key(), "") if strings.TrimSpace(value) == "" { return nil, nil } @@ -187,24 +191,24 @@ func (e EnvironmentCommand) Get() ([]string, error) { // KeyValue will get the string representation of the key+value func (e environmentBase) KeyValue(value string) string { - return fmt.Sprintf("%s=%s", e.key, value) + return fmt.Sprintf("%s=%s", e.key(), value) } // Setenv will do an environment set for the value to key func (e environmentBase) Set(value string) error { - unset, err := IsUnset(e.key, value) + unset, err := IsUnset(e.key(), value) if err != nil { return err } if unset { return nil } - return os.Setenv(e.key, value) + return os.Setenv(e.key(), value) } // Get will retrieve the value with the formatted input included func (e EnvironmentFormatter) Get(value string) string { - return e.fxn(e.key, value) + return e.fxn(e.key(), value) } func (e EnvironmentString) values() (string, []string) { @@ -346,8 +350,8 @@ func Environ() []string { var results []string for _, k := range os.Environ() { for _, r := range registry { - key := r.self().key - if key == EnvConfig.key { + key := r.self().key() + if key == EnvConfig.key() { continue } key = fmt.Sprintf("%s=", key) @@ -371,7 +375,7 @@ func ExpandParsed(inputs map[string]string) (map[string]string, error) { } var err error var cycles int - possibleCycles, ok := inputs[envConfigExpands.key] + possibleCycles, ok := inputs[envConfigExpands.key()] if ok { cycles, err = strconv.Atoi(possibleCycles) } else { diff --git a/internal/config/vars.go b/internal/config/vars.go @@ -11,8 +11,7 @@ import ( ) const ( - prefixKey = "LOCKBOX_" - clipBaseEnv = prefixKey + "CLIP_" + clipBaseEnv = "CLIP_" commandArgsExample = "[cmd args...]" fileExample = "<file>" detectedValue = "<detected>" @@ -29,8 +28,6 @@ const ( JSONDataOutputBlank JSONOutputMode = "empty" // JSONDataOutputRaw means the RAW (unencrypted) value is displayed JSONDataOutputRaw JSONOutputMode = "plaintext" - // EnvironmentCompletionKey controls which completion function to use - EnvironmentCompletionKey = prefixKey + "COMPLETION_FUNCTION" ) var ( @@ -44,123 +41,123 @@ var ( // EnvClipMax gets the maximum clipboard time EnvClipMax = EnvironmentInt{ environmentBase: environmentBase{ - key: clipBaseEnv + "MAX", - desc: "Override the amount of time before totp clears the clipboard (seconds).", + subKey: clipBaseEnv + "MAX", + desc: "Override the amount of time before totp clears the clipboard (seconds).", }, shortDesc: "clipboard max time", allowZero: false, defaultValue: 45, } // EnvHashLength handles the hashing output length EnvHashLength = EnvironmentInt{ environmentBase: environmentBase{ - key: EnvJSONDataOutput.key + "_HASH_LENGTH", - desc: fmt.Sprintf("Maximum hash string length the JSON output should contain when '%s' mode is set for JSON output.", JSONDataOutputHash), + subKey: EnvJSONDataOutput.subKey + "_HASH_LENGTH", + desc: fmt.Sprintf("Maximum hash string length the JSON output should contain when '%s' mode is set for JSON output.", JSONDataOutputHash), }, shortDesc: "hash length", allowZero: true, defaultValue: 0, } // EnvClipOSC52 indicates if OSC52 clipboard mode is enabled EnvClipOSC52 = EnvironmentBool{environmentBase: environmentBase{ - key: clipBaseEnv + "OSC52", - desc: "Enable OSC52 clipboard mode.", + subKey: clipBaseEnv + "OSC52", + desc: "Enable OSC52 clipboard mode.", }, defaultValue: false} // EnvNoTOTP indicates if TOTP is disabled EnvNoTOTP = EnvironmentBool{ environmentBase: environmentBase{ - key: prefixKey + "NOTOTP", - desc: "Disable TOTP integrations.", + subKey: "NOTOTP", + desc: "Disable TOTP integrations.", }, defaultValue: false, } // EnvReadOnly indicates if in read-only mode EnvReadOnly = EnvironmentBool{environmentBase: environmentBase{ - key: prefixKey + "READONLY", - desc: "Operate in readonly mode.", + subKey: "READONLY", + desc: "Operate in readonly mode.", }, defaultValue: false} // EnvNoClip indicates clipboard functionality is off EnvNoClip = EnvironmentBool{ environmentBase: environmentBase{ - key: prefixKey + "NOCLIP", - desc: "Disable clipboard operations.", + subKey: "NOCLIP", + desc: "Disable clipboard operations.", }, defaultValue: false, } // EnvNoColor indicates if color outputs are disabled EnvNoColor = EnvironmentBool{environmentBase: environmentBase{ - key: prefixKey + "NOCOLOR", - desc: "Disable terminal colors.", + subKey: "NOCOLOR", + desc: "Disable terminal colors.", }, defaultValue: false} // EnvInteractive indicates if operating in interactive mode EnvInteractive = EnvironmentBool{environmentBase: environmentBase{ - key: prefixKey + "INTERACTIVE", - desc: "Enable interactive mode.", + subKey: "INTERACTIVE", + desc: "Enable interactive mode.", }, defaultValue: true} // EnvMaxTOTP is the max TOTP time to run (default) EnvMaxTOTP = EnvironmentInt{environmentBase: environmentBase{ - key: EnvTOTPToken.key + "_MAX", - desc: "Time, in seconds, in which to show a TOTP token before automatically exiting.", + subKey: EnvTOTPToken.subKey + "_MAX", + desc: "Time, in seconds, in which to show a TOTP token before automatically exiting.", }, shortDesc: "max totp time", allowZero: false, defaultValue: 120} // EnvTOTPToken is the leaf token to use to store TOTP tokens EnvTOTPToken = EnvironmentString{environmentBase: environmentBase{ - key: prefixKey + "TOTP", - desc: "Attribute name to store TOTP tokens within the database.", + subKey: "TOTP", + desc: "Attribute name to store TOTP tokens within the database.", }, allowed: []string{"<string>"}, canDefault: true, defaultValue: "totp"} // EnvPlatform is the platform that the application is running on EnvPlatform = EnvironmentString{environmentBase: environmentBase{ - key: prefixKey + "PLATFORM", - desc: "Override the detected platform.", + subKey: "PLATFORM", + desc: "Override the detected platform.", }, defaultValue: detectedValue, allowed: Platforms, canDefault: false} // EnvStore is the location of the keepass file/store EnvStore = EnvironmentString{environmentBase: environmentBase{ - key: prefixKey + "STORE", - desc: "Directory to the database file.", requirement: "must be set", + subKey: "STORE", + desc: "Directory to the database file.", requirement: "must be set", }, canDefault: false, allowed: []string{fileExample}} // EnvHookDir is the directory of hooks to execute EnvHookDir = EnvironmentString{environmentBase: environmentBase{ - key: prefixKey + "HOOKDIR", - desc: "The path to hooks to execute on actions against the database.", + subKey: "HOOKDIR", + desc: "The path to hooks to execute on actions against the database.", }, allowed: []string{"<directory>"}, canDefault: true, defaultValue: ""} // EnvClipCopy allows overriding the clipboard copy command EnvClipCopy = EnvironmentCommand{environmentBase: environmentBase{ - key: clipBaseEnv + "COPY", - desc: "Override the detected platform copy command.", + subKey: clipBaseEnv + "COPY", + desc: "Override the detected platform copy command.", }} // EnvClipPaste allows overriding the clipboard paste command EnvClipPaste = EnvironmentCommand{environmentBase: environmentBase{ - key: clipBaseEnv + "PASTE", - desc: "Override the detected platform paste command.", + subKey: clipBaseEnv + "PASTE", + desc: "Override the detected platform paste command.", }} // EnvTOTPColorBetween handles terminal coloring for TOTP windows (seconds) EnvTOTPColorBetween = EnvironmentString{environmentBase: environmentBase{ - key: EnvTOTPToken.key + "_BETWEEN", + subKey: EnvTOTPToken.subKey + "_BETWEEN", desc: fmt.Sprintf(`Override when to set totp generated outputs to different colors, must be a list of one (or more) rules where a '%s' delimits the start and end second (0-60 for each), and '%s' allows for multiple windows.`, colorWindowSpan, colorWindowDelimiter), }, canDefault: true, defaultValue: TOTPDefaultBetween, allowed: exampleColorWindows} // EnvKeyFile is an keyfile for the database EnvKeyFile = EnvironmentString{environmentBase: environmentBase{ - key: prefixKey + "KEYFILE", requirement: requiredKeyOrKeyFile, + subKey: "KEYFILE", requirement: requiredKeyOrKeyFile, desc: "A keyfile to access/protect the database.", }, allowed: []string{"keyfile"}, canDefault: true, defaultValue: ""} // EnvModTime is modtime override ability for entries EnvModTime = EnvironmentString{environmentBase: environmentBase{ - key: prefixKey + "SET_MODTIME", - desc: fmt.Sprintf("Input modification time to set for the entry\n\nExpected format: %s.", ModTimeFormat), + subKey: "SET_MODTIME", + desc: fmt.Sprintf("Input modification time to set for the entry\n\nExpected format: %s.", ModTimeFormat), }, canDefault: true, defaultValue: "", allowed: []string{"modtime"}} // EnvJSONDataOutput controls how JSON is output in the 'data' field EnvJSONDataOutput = EnvironmentString{ environmentBase: environmentBase{ - key: prefixKey + "JSON_DATA", - desc: fmt.Sprintf("Changes what the data field in JSON outputs will contain.\n\nUse '%s' with CAUTION.", JSONDataOutputRaw), + subKey: "JSON_DATA", + desc: fmt.Sprintf("Changes what the data field in JSON outputs will contain.\n\nUse '%s' with CAUTION.", JSONDataOutputRaw), }, canDefault: true, defaultValue: string(JSONDataOutputHash), allowed: []string{string(JSONDataOutputRaw), string(JSONDataOutputHash), string(JSONDataOutputBlank)}, } // EnvFormatTOTP supports formatting the TOTP tokens for generation of tokens EnvFormatTOTP = EnvironmentFormatter{environmentBase: environmentBase{ - key: EnvTOTPToken.key + "_FORMAT", - desc: "Override the otpauth url used to store totp tokens. It must have ONE format string ('%s') to insert the totp base code.", + subKey: EnvTOTPToken.subKey + "_FORMAT", + desc: "Override the otpauth url used to store totp tokens. It must have ONE format string ('%s') to insert the totp base code.", }, fxn: formatterTOTP, allowed: "otpauth//url/%s/args..."} // EnvConfig is the location of the config file to read environment variables from EnvConfig = EnvironmentString{environmentBase: environmentBase{ - key: prefixKey + "ENV", + subKey: "ENV", desc: fmt.Sprintf(`Allows setting a specific file of environment variables for lockbox to read and use as configuration values (an '.env' file). The keyword '%s' will disable this functionality and the keyword '%s' will search for a file in the following paths in the user's home directory matching the first file found. @@ -171,13 +168,15 @@ Note that this setting is not output as part of the environment.`, noEnvironment }, canDefault: true, defaultValue: detectEnvironment, allowed: []string{detectEnvironment, fileExample, noEnvironment}} // EnvCompletion is the completion method to use EnvCompletion = EnvironmentString{environmentBase: environmentBase{ - key: EnvironmentCompletionKey, + subKey: "COMPLETION_FUNCTION", desc: "Use to select the non-default completions, please review the shell completion help for more information.", requirement: "must be exported via a shell variable", }, canDefault: false} - envKeyMode = EnvironmentString{ + // EnvironmentCompletionKey is the underlying key for managing completion functions + EnvironmentCompletionKey = EnvCompletion.key() + envKeyMode = EnvironmentString{ environmentBase: environmentBase{ - key: prefixKey + "KEYMODE", requirement: "must be set to a valid mode when using a key", + subKey: "KEYMODE", requirement: "must be set to a valid mode when using a key", desc: fmt.Sprintf(`How to retrieve the database store password. Set to '%s' when only using a key file. Set to '%s' to ignore the set key value`, noKeyMode, IgnoreKeyMode), whenUnset: string(DefaultKeyMode), }, @@ -185,13 +184,13 @@ Set to '%s' to ignore the set key value`, noKeyMode, IgnoreKeyMode), whenUnset: canDefault: true, defaultValue: "", } envKey = EnvironmentString{environmentBase: environmentBase{ - requirement: requiredKeyOrKeyFile, key: prefixKey + "KEY", + requirement: requiredKeyOrKeyFile, subKey: "KEY", desc: fmt.Sprintf("The database key ('%s' mode) or command to run ('%s' mode) to retrieve the database password.", plainKeyMode, commandKeyMode), }, allowed: []string{commandArgsExample, "password"}, canDefault: false} envConfigExpands = EnvironmentInt{environmentBase: environmentBase{ - key: EnvConfig.key + "_EXPANDS", + subKey: EnvConfig.subKey + "_EXPANDS", desc: `The maximum number of times to expand the input env to resolve variables (set to 0 to disable expansion). This value can NOT be an expansion itself.`, @@ -250,7 +249,7 @@ func ListEnvironmentVariables() []string { if r != "" { requirement = r } - text := fmt.Sprintf("\n%s\n%s requirement: %s\n default: %s\n options: %s\n", env.key, description, requirement, value, strings.Join(allow, "|")) + text := fmt.Sprintf("\n%s\n%s requirement: %s\n default: %s\n options: %s\n", env.key(), description, requirement, value, strings.Join(allow, "|")) results = append(results, text) } sort.Strings(results)