package mill import ( "context" "errors" "fmt" "github.com/bluesky-social/indigo/atproto/syntax" gossh "golang.org/x/crypto/ssh" millproto "tangled.org/core/spindle/mill/proto" millv1 "tangled.org/core/spindle/mill/proto/gen" ) // the spindle's own check, the mill only picks the repo type DebugKeyChecker interface { DebugKeyAllowed(ctx context.Context, repoDid syntax.DID, key gossh.PublicKey) bool } func (m *Mill) SetDebugKeyChecker(c DebugKeyChecker) { m.mu.Lock() defer m.mu.Unlock() m.debugKeys = c } func (m *Mill) handleDebugKeyRequest(s *millSession, req *millv1.DebugKeyRequest) { resp := &millv1.DebugKeyResponse{RequestId: req.GetRequestId()} allowed, err := m.debugKeyAllowed(s, req) if err != nil { resp.Error = err.Error() } resp.Allowed = allowed && err == nil _ = s.send(&millproto.Message{DebugKeyResp: resp}) } // the repo comes from the lease this node was given, never from the executor func (m *Mill) debugKeyAllowed(s *millSession, req *millv1.DebugKeyRequest) (bool, error) { m.mu.Lock() checker := m.debugKeys lease := m.leases[req.GetLeaseId()] m.mu.Unlock() if checker == nil { return false, errors.New("no debug key checker attached") } if lease == nil || lease.nodeID != s.nodeID || lease.epoch != s.epoch { return false, fmt.Errorf("no live lease %q on this node with matching epoch", req.GetLeaseId()) } lease.mu.Lock() repo := lease.repoDID lease.mu.Unlock() repoDid, err := syntax.ParseDID(repo) if err != nil { return false, fmt.Errorf("lease has no usable repo: %w", err) } key, err := gossh.ParsePublicKey(req.GetPublicKey()) if err != nil { return false, fmt.Errorf("bad public key: %w", err) } return checker.DebugKeyAllowed(s.ctx, repoDid, key), nil }