Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d74cb78

Browse files
committed
fix(agent/agentssh): pin random seed for RSA key generation
Change-Id: I8c7e3070324e5d558374fd6891eea9d48660e1e9 Signed-off-by: Thomas Kosiewski <[email protected]>
1 parent 4732f08 commit d74cb78

File tree

2 files changed

+33
-8
lines changed

2 files changed

+33
-8
lines changed

agent/agent.go

+17-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"encoding/json"
77
"errors"
88
"fmt"
9+
"hash/fnv"
910
"io"
1011
"net/http"
1112
"net/netip"
@@ -272,6 +273,7 @@ func (a *agent) init() {
272273
UpdateEnv: a.updateCommandEnv,
273274
WorkingDirectory: func() string { return a.manifest.Load().Directory },
274275
BlockFileTransfer: a.blockFileTransfer,
276+
RandomSeed: stringToInt64Hash(&a.manifest),
275277
})
276278
if err != nil {
277279
panic(err)
@@ -372,7 +374,6 @@ func (a *agent) collectMetadata(ctx context.Context, md codersdk.WorkspaceAgentM
372374
// Important: if the command times out, we may see a misleading error like
373375
// "exit status 1", so it's important to include the context error.
374376
err = errors.Join(err, ctx.Err())
375-
376377
if err != nil {
377378
result.Error = fmt.Sprintf("run cmd: %+v", err)
378379
}
@@ -1850,3 +1851,18 @@ func PrometheusMetricsHandler(prometheusRegistry *prometheus.Registry, logger sl
18501851
}
18511852
})
18521853
}
1854+
1855+
// stringToInt64Hash converts the manifest's AgentID and WorkspaceID to an int64 hash.
1856+
// This uses the FNV-1a hash algorithm which provides decent distribution and collision
1857+
// resistance for string inputs.
1858+
func stringToInt64Hash(manifest *atomic.Pointer[agentsdk.Manifest]) int64 {
1859+
m := manifest.Load()
1860+
if m == nil {
1861+
return 42
1862+
}
1863+
1864+
h := fnv.New64a()
1865+
h.Write(m.AgentID[:])
1866+
h.Write(m.WorkspaceID[:])
1867+
return int64(h.Sum64())
1868+
}

agent/agentssh/agentssh.go

+16-7
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ package agentssh
33
import (
44
"bufio"
55
"context"
6-
"crypto/rand"
76
"crypto/rsa"
87
"errors"
98
"fmt"
109
"io"
10+
"math/rand"
1111
"net"
1212
"os"
1313
"os/exec"
@@ -85,6 +85,10 @@ type Config struct {
8585
X11DisplayOffset *int
8686
// BlockFileTransfer restricts use of file transfer applications.
8787
BlockFileTransfer bool
88+
89+
// RandomSeed is a random seed value exclusively used to generate a
90+
// deterministic SSH host key.
91+
RandomSeed int64
8892
}
8993

9094
type Server struct {
@@ -112,20 +116,25 @@ type Server struct {
112116
}
113117

114118
func NewServer(ctx context.Context, logger slog.Logger, prometheusRegistry *prometheus.Registry, fs afero.Fs, execer agentexec.Execer, config *Config) (*Server, error) {
119+
if config == nil {
120+
config = &Config{}
121+
}
122+
115123
// Clients' should ignore the host key when connecting.
116124
// The agent needs to authenticate with coderd to SSH,
117125
// so SSH authentication doesn't improve security.
118-
randomHostKey, err := rsa.GenerateKey(rand.Reader, 2048)
126+
127+
// Create a deterministic random source
128+
// nolint: gosec
129+
deterministicRand := rand.New(rand.NewSource(config.RandomSeed))
130+
coderHostKey, err := rsa.GenerateKey(deterministicRand, 2048)
119131
if err != nil {
120132
return nil, err
121133
}
122-
randomSigner, err := gossh.NewSignerFromKey(randomHostKey)
134+
coderSigner, err := gossh.NewSignerFromKey(coderHostKey)
123135
if err != nil {
124136
return nil, err
125137
}
126-
if config == nil {
127-
config = &Config{}
128-
}
129138
if config.X11DisplayOffset == nil {
130139
offset := X11DefaultDisplayOffset
131140
config.X11DisplayOffset = &offset
@@ -190,7 +199,7 @@ func NewServer(ctx context.Context, logger slog.Logger, prometheusRegistry *prom
190199
slog.Error(err))
191200
},
192201
Handler: s.sessionHandler,
193-
HostSigners: []ssh.Signer{randomSigner},
202+
HostSigners: []ssh.Signer{coderSigner},
194203
LocalPortForwardingCallback: func(ctx ssh.Context, destinationHost string, destinationPort uint32) bool {
195204
// Allow local port forwarding all!
196205
s.logger.Debug(ctx, "local port forward",

0 commit comments

Comments
 (0)