Skip to content

spawn plugin install requires SSH, so it cannot work on a keyless SSM-only instance #855

Open

Description

@scttfrdmn

Found while withdrawing #810, and filed because that change deletes the only sketch of
the missing capability
— pkg/plugin/push_ssm.go. Naming the gap so it is not lost with
the code.

The gap

spawn plugin install reaches spored's push API over an SSH port-forward, unconditionally:

token, err := sshReadToken(ctx, instance, pluginKeyPath)
_, err = withSSHTunnel(ctx, instance, pluginKeyPath, func() (*http.Response, error) {
    req, _ := http.NewRequestWithContext(ctx, http.MethodPost,
        "http://127.0.0.1:7777/v1/plugins/install", bytes.NewReader(payload))

withSSHTunnel shells out to ssh -N -L 7777:127.0.0.1:7777. Both the token read and the
tunnel need a local private key.

So on an instance with no local key, plugin install cannot work — and those are instances
spawn deliberately supports:

A launch that works keyless produces an instance that cannot take a plugin.

What #810 removed, and why it is relevant

pkg/plugin/push_ssm.go implemented PushClient over SSM Parameter Store — 52 lines,
never constructed. It was deleted as dead code, correctly: it duplicated nothing that works
and nothing called it.

But it was a sketch of this. The SSM delivery idea existed; the wiring never did. Worth
having the gap on record rather than inferring it again from the absence.

What a fix needs

The hard part is not the transport, it is that the push API is loopback-only (correctly
— pkg/pluginruntime/pushapi.go binds 127.0.0.1 with a per-start 32-byte token). So an
SSM path cannot simply POST to it from outside; it has to either:

  1. run the install request on the instance via ssm:SendCommand (curl to loopback with
    the token read locally), which is how the reaper and spawn connect already reach
    SSM-only hosts; or
  2. have spored poll SSM Parameter Store for install requests, which is what the deleted
    push_ssm.go gestured at — and which adds a polling loop and a parameter-store lifecycle
    to maintain.

(1) reuses machinery that exists and keeps the token local. (2) was the sketch. I have not
chosen between them; that is the decision this issue carries.

Not urgent

Nothing is broken that used to work — plugin install has always needed SSH. This is a
capability gap on a supported configuration, so the cost is "plugins are unavailable on
keyless instances", not a failure.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions