utils
created pr with
99.1
added 99.2
1: b41f14a ! 1: dca5cae feat: add ssh cert file support to ssh client impl
added 99.3
1: dca5cae = 1: dca5cae feat: add ssh cert file support to ssh client impl
-: ------- > 2: 31cd283 refactor: CertificateFile -> CertificateLocation
cmds
checkout latest patchset:
ssh pr.pico.sh print 99 | git am -3checkout any patchset in a patch request:
ssh pr.pico.sh print 99.[rev] | git am -3add changes to patch request:
git format-patch main --stdout | ssh pr.pico.sh pr add 99
Patchset
99.3
feat: add ssh cert file support to ssh client impl
Eric Bower
2025-12-25T04:18:34ZOriginal impl: https://github.com/picosh/utils/blob/main/pipe/client.go#L193
Semantic diff summary
0 added,
2 modified,
0 signature changed,
0 removed
across 1 analyzed file
+33
-5
pipe/client.go
#
| ... | ... | @@ -182,11 +182,12 @@ func (c *Client) RemoveSession(id string) error { | |
| 182 | 182 | ||
| 183 | 183 | // SSHClientInfo represents the SSH connection information. | |
| 184 | 184 | type SSHClientInfo struct { | |
| 185 | - | RemoteHost string | |
| 186 | - | RemoteHostname string | |
| 187 | - | RemoteUser string | |
| 188 | - | KeyLocation string | |
| 189 | - | KeyPassphrase string | |
| 185 | + | RemoteHost string | |
| 186 | + | RemoteHostname string | |
| 187 | + | RemoteUser string | |
| 188 | + | KeyLocation string | |
| 189 | + | KeyPassphrase string | |
| 190 | + | CertificateFile string | |
| 190 | 191 | } | |
| 191 | 192 | ||
| 192 | 193 | // NewSSHClient creates a new SSH client. |
| ... | ... | @@ -226,6 +227,33 @@ func NewSSHClient(info *SSHClientInfo) (*ssh.Client, error) { | |
| 226 | 227 | if err != nil { | |
| 227 | 228 | return nil, err | |
| 228 | 229 | } | |
| 230 | + | ||
| 231 | + | if info.CertificateFile != "" { | |
| 232 | + | certPath, err := filepath.Abs(info.CertificateFile) | |
| 233 | + | if err != nil { | |
| 234 | + | return nil, err | |
| 235 | + | } | |
| 236 | + | ||
| 237 | + | certData, err := os.ReadFile(certPath) | |
| 238 | + | if err != nil { | |
| 239 | + | return nil, err | |
| 240 | + | } | |
| 241 | + | ||
| 242 | + | pubKey, _, _, _, err := ssh.ParseAuthorizedKey(certData) | |
| 243 | + | if err != nil { | |
| 244 | + | return nil, fmt.Errorf("failed to parse certificate: %w", err) | |
| 245 | + | } | |
| 246 | + | ||
| 247 | + | cert, ok := pubKey.(*ssh.Certificate) | |
| 248 | + | if !ok { | |
| 249 | + | return nil, fmt.Errorf("file is not an SSH certificate") | |
| 250 | + | } | |
| 251 | + | ||
| 252 | + | signer, err = ssh.NewCertSigner(cert, signer) | |
| 253 | + | if err != nil { | |
| 254 | + | return nil, fmt.Errorf("failed to create cert signer: %w", err) | |
| 255 | + | } | |
| 256 | + | } | |
| 229 | 257 | } | |
| 230 | 258 | ||
| 231 | 259 | var authMethods []ssh.AuthMethod |