Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion ssh-manager/generate_ecdsa.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,25 @@ import (
"fmt"
)

// GenerateEcdsa creates a new ECDSA SSH key pair.
func (m *SshManager) GenerateEcdsa(
ctx context.Context,
// The remote host address (e.g., github.com).
remoteHost string,
// The user name on the remote host.
remoteUser string,
// The hostname of the local machine used for key naming.
// +optional
// +default="dagger"
localHostname string,
// The bit size for the ECDSA curve (256, 384, or 521).
// +optional
// +default=521
bits int,
// Automatically generate a 32-character passphrase for the private key.
// +optional
autoPassphrase bool,
// An existing SSH config file to append the new configuration to.
// +optional
existingConfig *dagger.File,
) (*KeyResult, error) {
Expand All @@ -33,7 +40,7 @@ func (m *SshManager) GenerateEcdsa(
case 521:
curve = elliptic.P521()
default:
return nil, fmt.Errorf("invalid bits for ecdsa")
return nil, fmt.Errorf("invalid bits for ecdsa: must be 256, 384, or 521")
}
priv, err := ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
Expand Down
6 changes: 6 additions & 0 deletions ssh-manager/generate_ed25519.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,21 @@ import (
"dagger/ssh-manager/internal/dagger"
)

// GenerateEd25519 creates a new Ed25519 SSH key pair. This is the recommended modern algorithm.
func (m *SshManager) GenerateEd25519(
ctx context.Context,
// The remote host address (e.g., github.com).
remoteHost string,
// The user name on the remote host.
remoteUser string,
// The hostname of the local machine used for key naming.
// +optional
// +default="dagger"
localHostname string,
// Automatically generate a 32-character passphrase for the private key.
// +optional
autoPassphrase bool,
// An existing SSH config file to append the new configuration to.
// +optional
existingConfig *dagger.File,
) (*KeyResult, error) {
Expand Down
93 changes: 14 additions & 79 deletions ssh-manager/main.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// SSH Manager module for generating secure SSH key pairs and configurations.
package main

import (
Expand All @@ -15,89 +16,22 @@ import (
"golang.org/x/crypto/ssh"
)

type SshManager struct{}
// SshManager provides services to generate and manage SSH identities.
type SshManager struct{} //revive:disable-line

// KeyResult represents the collection of generated SSH components.
type KeyResult struct {
PublicKey *dagger.File `json:"publicKey"`
PrivateKey *dagger.Secret `json:"privateKey"`
Config *dagger.File `json:"config"`
Files *dagger.Directory `json:"files"`
// The OpenSSH formatted public key file.
PublicKey *dagger.File `json:"publicKey"`
// The OpenSSH formatted private key, stored as a secret.
PrivateKey *dagger.Secret `json:"privateKey"`
// The SSH configuration file containing host and proxy settings.
Config *dagger.File `json:"config"`
// A directory containing the private key, public key, and config for easy export.
Files *dagger.Directory `json:"files"`
}

// func (m *SshManager) GenerateRsa(
// ctx context.Context,
// remoteHost string,
// remoteUser string,
// // +optional
// // +default="dagger"
// localHostname string,
// // +optional
// // +default=4096
// bits int,
// // +optional
// autoPassphrase bool,
// // +optional
// existingConfig *dagger.File,
// ) (*KeyResult, error) {
// priv, err := rsa.GenerateKey(rand.Reader, bits)
// if err != nil {
// return nil, err
// }
// return m.finalize(ctx, priv, priv.Public(), "rsa", remoteHost, remoteUser, localHostname, autoPassphrase, existingConfig)
// }

/* func (m *SshManager) GenerateEd25519(
ctx context.Context,
remoteHost string,
remoteUser string,
// +optional
// +default="dagger"
localHostname string,
// +optional
autoPassphrase bool,
// +optional
existingConfig *dagger.File,
) (*KeyResult, error) {
pub, priv, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
return nil, err
}
return m.finalize(ctx, priv, pub, "ed25519", remoteHost, remoteUser, localHostname, autoPassphrase, existingConfig)
} */

// func (m *SshManager) GenerateEcdsa(
// ctx context.Context,
// remoteHost string,
// remoteUser string,
// // +optional
// // +default="dagger"
// localHostname string,
// // +optional
// // +default=521
// bits int,
// // +optional
// autoPassphrase bool,
// // +optional
// existingConfig *dagger.File,
// ) (*KeyResult, error) {
// var curve elliptic.Curve
// switch bits {
// case 256:
// curve = elliptic.P256()
// case 384:
// curve = elliptic.P384()
// case 521:
// curve = elliptic.P521()
// default:
// return nil, fmt.Errorf("invalid bits for ecdsa")
// }
// priv, err := ecdsa.GenerateKey(curve, rand.Reader)
// if err != nil {
// return nil, err
// }
// return m.finalize(ctx, priv, priv.Public(), "ecdsa", remoteHost, remoteUser, localHostname, autoPassphrase, existingConfig)
// }

// finalize is an internal helper to process raw keys into formatted files and secrets.
func (m *SshManager) finalize(
ctx context.Context,
priv any,
Expand Down Expand Up @@ -169,6 +103,7 @@ func (m *SshManager) finalize(
}, nil
}

// randomString generates a cryptographically secure random string for passphrases.
func (m *SshManager) randomString(n int) string {
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()"
ret := make([]byte, n)
Expand Down
7 changes: 7 additions & 0 deletions ssh-manager/rsa.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,25 @@ import (
"dagger/ssh-manager/internal/dagger"
)

// GenerateRsa creates a new RSA SSH key pair.
func (m *SshManager) GenerateRsa(
ctx context.Context,
// The remote host address (e.g., github.com).
remoteHost string,
// The user name on the remote host.
remoteUser string,
// The hostname of the local machine used for key naming.
// +optional
// +default="dagger"
localHostname string,
// The bit length for the RSA key.
// +optional
// +default=4096
bits int,
// Automatically generate a 32-character passphrase for the private key.
// +optional
autoPassphrase bool,
// An existing SSH config file to append the new configuration to.
// +optional
existingConfig *dagger.File,
) (*KeyResult, error) {
Expand Down
3 changes: 1 addition & 2 deletions ssh-manager/test/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
// The first line in this comment block is a short description line and the
// rest is a long description with more detail on the module's purpose or usage,
// if appropriate. All modules should have a short description.

package main

import (
Expand All @@ -23,7 +22,7 @@ import (
"github.com/sourcegraph/conc/pool"
)

type SshManagertest struct{}
type SshManagertest struct{} //revive:disable-line

// All runs all SSH key generation tests in parallel.
func (m *SshManagertest) All(ctx context.Context) error {
Expand Down
Loading