/
local.go
110 lines (94 loc) · 3.55 KB
/
local.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package keypairs
import (
"os"
"path/filepath"
"github.com/ActiveState/cli/internal/constants"
"github.com/ActiveState/cli/internal/errs"
"github.com/ActiveState/cli/internal/fileutils"
"github.com/ActiveState/cli/internal/locale"
"github.com/ActiveState/cli/internal/logging"
)
type Configurable interface {
ConfigPath() string
Close() error
Set(s string, i interface{}) error
GetString(s string) string
GetBool(s string) bool
}
// Load will attempt to load a Keypair using private and public-key files from
// the user's file system; specifically from the config dir. It is assumed that
// this keypair file has no passphrase, even if it is encrypted.
func Load(cfg Configurable, keyName string) (Keypair, error) {
keyFilename := LocalKeyFilename(cfg.ConfigPath(), keyName)
if err := validateKeyFile(keyFilename); err != nil {
return nil, err
}
return loadAndParseKeypair(keyFilename)
}
// Save will save the unencrypted and encoded private key to a local config
// file. The filename will be the value of `keyName` and suffixed with `.key`.
func Save(cfg Configurable, kp Keypair, keyName string) error {
keyFileName := LocalKeyFilename(cfg.ConfigPath(), keyName)
err := os.WriteFile(keyFileName, []byte(kp.EncodePrivateKey()), 0600)
if err != nil {
return errs.Wrap(err, "WriteFile failed")
}
return nil
}
// Delete will delete an unencrypted and encoded private key from the local
// config directory. The base filename (sans suffix) must be provided.
func Delete(cfg Configurable, keyName string) error {
filename := LocalKeyFilename(cfg.ConfigPath(), keyName)
if fileutils.FileExists(filename) {
if err := os.Remove(filename); err != nil {
return errs.Wrap(err, "os.Remove %s failed", filename)
}
}
return nil
}
// LoadWithDefaults will call Load with the default key name (i.e.
// constants.KeypairLocalFileName). If the key override is set
// (constants.PrivateKeyEnvVarName), that value will be parsed directly.
func LoadWithDefaults(cfg Configurable) (Keypair, error) {
if key := os.Getenv(constants.PrivateKeyEnvVarName); key != "" {
logging.Debug("Using private key sourced from environment")
return ParseRSA(key)
}
return Load(cfg, constants.KeypairLocalFileName)
}
// SaveWithDefaults will call Save with the provided keypair and the default
// key name (i.e. constants.KeypairLocalFileName). The operation will fail when
// the key override is set (constants.PrivateKeyEnvVarName).
func SaveWithDefaults(cfg Configurable, kp Keypair) error {
if hasKeyOverride() {
return locale.NewInputError("keypairs_err_override_with_save")
}
return Save(cfg, kp, constants.KeypairLocalFileName)
}
// DeleteWithDefaults will call Delete with the default key name (i.e.
// constants.KeypairLocalFileName). The operation will fail when the key
// override is set (constants.PrivateKeyEnvVarName).
func DeleteWithDefaults(cfg Configurable) error {
if hasKeyOverride() {
return locale.NewInputError("keypairs_err_override_with_delete")
}
return Delete(cfg, constants.KeypairLocalFileName)
}
// LocalKeyFilename returns the full filepath for the given key name
func LocalKeyFilename(configPath, keyName string) string {
return filepath.Join(configPath, keyName+".key")
}
func loadAndParseKeypair(keyFilename string) (Keypair, error) {
keyFileBytes, err := os.ReadFile(keyFilename)
if err != nil {
return nil, errs.Wrap(err, "ReadFile %s failed", keyFilename)
}
return ParseRSA(string(keyFileBytes))
}
func hasKeyOverride() bool {
if os.Getenv(constants.PrivateKeyEnvVarName) != "" {
logging.Debug("Has key override from env")
return true
}
return false
}