Remove file reading from bootstrap package
Signed-off-by: Philip Laine <philip.laine@gmail.com>
This commit is contained in:
@@ -18,6 +18,8 @@ package sourcesecret
|
||||
|
||||
import (
|
||||
"crypto/elliptic"
|
||||
|
||||
"github.com/fluxcd/pkg/ssh"
|
||||
)
|
||||
|
||||
type PrivateKeyAlgorithm string
|
||||
@@ -48,12 +50,12 @@ type Options struct {
|
||||
PrivateKeyAlgorithm PrivateKeyAlgorithm
|
||||
RSAKeyBits int
|
||||
ECDSACurve elliptic.Curve
|
||||
PrivateKeyPath string
|
||||
Keypair *ssh.KeyPair
|
||||
Username string
|
||||
Password string
|
||||
CAFilePath string
|
||||
CertFilePath string
|
||||
KeyFilePath string
|
||||
CAFile []byte
|
||||
CertFile []byte
|
||||
KeyFile []byte
|
||||
TargetPath string
|
||||
ManifestFile string
|
||||
}
|
||||
@@ -64,12 +66,11 @@ func MakeDefaultOptions() Options {
|
||||
Namespace: "flux-system",
|
||||
Labels: map[string]string{},
|
||||
PrivateKeyAlgorithm: RSAPrivateKeyAlgorithm,
|
||||
PrivateKeyPath: "",
|
||||
Username: "",
|
||||
Password: "",
|
||||
CAFilePath: "",
|
||||
CertFilePath: "",
|
||||
KeyFilePath: "",
|
||||
CAFile: []byte{},
|
||||
CertFile: []byte{},
|
||||
KeyFile: []byte{},
|
||||
ManifestFile: "secret.yaml",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,10 +66,8 @@ func Generate(options Options) (*manifestgen.Manifest, error) {
|
||||
switch {
|
||||
case options.Username != "" && options.Password != "":
|
||||
// noop
|
||||
case len(options.PrivateKeyPath) > 0:
|
||||
if keypair, err = loadKeyPair(options.PrivateKeyPath, options.Password); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case options.Keypair != nil:
|
||||
keypair = options.Keypair
|
||||
case len(options.PrivateKeyAlgorithm) > 0:
|
||||
if keypair, err = generateKeyPair(options); err != nil {
|
||||
return nil, err
|
||||
@@ -83,23 +81,6 @@ func Generate(options Options) (*manifestgen.Manifest, error) {
|
||||
}
|
||||
}
|
||||
|
||||
var caFile []byte
|
||||
if options.CAFilePath != "" {
|
||||
if caFile, err = os.ReadFile(options.CAFilePath); err != nil {
|
||||
return nil, fmt.Errorf("failed to read CA file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
var certFile, keyFile []byte
|
||||
if options.CertFilePath != "" && options.KeyFilePath != "" {
|
||||
if certFile, err = os.ReadFile(options.CertFilePath); err != nil {
|
||||
return nil, fmt.Errorf("failed to read cert file: %w", err)
|
||||
}
|
||||
if keyFile, err = os.ReadFile(options.KeyFilePath); err != nil {
|
||||
return nil, fmt.Errorf("failed to read key file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
var dockerCfgJson []byte
|
||||
if options.Registry != "" {
|
||||
dockerCfgJson, err = generateDockerConfigJson(options.Registry, options.Username, options.Password)
|
||||
@@ -108,7 +89,7 @@ func Generate(options Options) (*manifestgen.Manifest, error) {
|
||||
}
|
||||
}
|
||||
|
||||
secret := buildSecret(keypair, hostKey, caFile, certFile, keyFile, dockerCfgJson, options)
|
||||
secret := buildSecret(keypair, hostKey, options.CAFile, options.CertFile, options.KeyFile, dockerCfgJson, options)
|
||||
b, err := yaml.Marshal(secret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -120,6 +101,35 @@ func Generate(options Options) (*manifestgen.Manifest, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func LoadKeyPairFromPath(path, password string) (*ssh.KeyPair, error) {
|
||||
if path == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
b, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open private key file: %w", err)
|
||||
}
|
||||
return LoadKeyPair(b, password)
|
||||
}
|
||||
|
||||
func LoadKeyPair(privateKey []byte, password string) (*ssh.KeyPair, error) {
|
||||
var ppk cryptssh.Signer
|
||||
var err error
|
||||
if password != "" {
|
||||
ppk, err = cryptssh.ParsePrivateKeyWithPassphrase(privateKey, []byte(password))
|
||||
} else {
|
||||
ppk, err = cryptssh.ParsePrivateKey(privateKey)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ssh.KeyPair{
|
||||
PublicKey: cryptssh.MarshalAuthorizedKey(ppk.PublicKey()),
|
||||
PrivateKey: privateKey,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func buildSecret(keypair *ssh.KeyPair, hostKey, caFile, certFile, keyFile, dockerCfg []byte, options Options) (secret corev1.Secret) {
|
||||
secret.TypeMeta = metav1.TypeMeta{
|
||||
APIVersion: "v1",
|
||||
@@ -143,16 +153,16 @@ func buildSecret(keypair *ssh.KeyPair, hostKey, caFile, certFile, keyFile, docke
|
||||
secret.StringData[PasswordSecretKey] = options.Password
|
||||
}
|
||||
|
||||
if caFile != nil {
|
||||
if len(caFile) != 0 {
|
||||
secret.StringData[CAFileSecretKey] = string(caFile)
|
||||
}
|
||||
|
||||
if certFile != nil && keyFile != nil {
|
||||
if len(certFile) != 0 && len(keyFile) != 0 {
|
||||
secret.StringData[CertFileSecretKey] = string(certFile)
|
||||
secret.StringData[KeyFileSecretKey] = string(keyFile)
|
||||
}
|
||||
|
||||
if keypair != nil && hostKey != nil {
|
||||
if keypair != nil && len(hostKey) != 0 {
|
||||
secret.StringData[PrivateKeySecretKey] = string(keypair.PrivateKey)
|
||||
secret.StringData[PublicKeySecretKey] = string(keypair.PublicKey)
|
||||
secret.StringData[KnownHostsSecretKey] = string(hostKey)
|
||||
@@ -165,29 +175,6 @@ func buildSecret(keypair *ssh.KeyPair, hostKey, caFile, certFile, keyFile, docke
|
||||
return
|
||||
}
|
||||
|
||||
func loadKeyPair(path string, password string) (*ssh.KeyPair, error) {
|
||||
b, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open private key file: %w", err)
|
||||
}
|
||||
|
||||
var ppk cryptssh.Signer
|
||||
if password != "" {
|
||||
ppk, err = cryptssh.ParsePrivateKeyWithPassphrase(b, []byte(password))
|
||||
} else {
|
||||
ppk, err = cryptssh.ParsePrivateKey(b)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ssh.KeyPair{
|
||||
PublicKey: cryptssh.MarshalAuthorizedKey(ppk.PublicKey()),
|
||||
PrivateKey: b,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func generateKeyPair(options Options) (*ssh.KeyPair, error) {
|
||||
var keyGen ssh.KeyPairGenerator
|
||||
switch options.PrivateKeyAlgorithm {
|
||||
|
||||
@@ -48,7 +48,7 @@ func Test_passwordLoadKeyPair(t *testing.T) {
|
||||
pk, _ := os.ReadFile(tt.privateKeyPath)
|
||||
ppk, _ := os.ReadFile(tt.publicKeyPath)
|
||||
|
||||
got, err := loadKeyPair(tt.privateKeyPath, tt.password)
|
||||
got, err := LoadKeyPair(pk, tt.password)
|
||||
if err != nil {
|
||||
t.Errorf("loadKeyPair() error = %v", err)
|
||||
return
|
||||
@@ -67,24 +67,13 @@ func Test_passwordLoadKeyPair(t *testing.T) {
|
||||
func Test_PasswordlessLoadKeyPair(t *testing.T) {
|
||||
for algo, privateKey := range testdata.PEMBytes {
|
||||
t.Run(algo, func(t *testing.T) {
|
||||
f, err := os.CreateTemp("", "test-private-key-")
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create temporary file. err: %s", err)
|
||||
}
|
||||
defer os.Remove(f.Name())
|
||||
|
||||
if _, err = f.Write(privateKey); err != nil {
|
||||
t.Fatalf("unable to write private key to file. err: %s", err)
|
||||
}
|
||||
|
||||
got, err := loadKeyPair(f.Name(), "")
|
||||
got, err := LoadKeyPair(privateKey, "")
|
||||
if err != nil {
|
||||
t.Errorf("loadKeyPair() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
pk, _ := os.ReadFile(f.Name())
|
||||
if !reflect.DeepEqual(got.PrivateKey, pk) {
|
||||
if !reflect.DeepEqual(got.PrivateKey, privateKey) {
|
||||
t.Errorf("PrivateKey %s != %s", got.PrivateKey, string(privateKey))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user