kubernetes/kops · error

forwarding ssh auth to keyring: %w

Error message

forwarding ssh auth to keyring: %w

What it means

When Dial connects through a bastion (useBastion=true), it forwards SSH agent authentication to the keyring via agent.ForwardToAgent on the established client. If that forwarding call fails, the error is wrapped with this message and returned from Dial. It means the TCP+SSH handshake succeeded but agent forwarding setup over the client failed.

Source

Thrown at pkg/dump/dumper.go:704

		Timeout: 5 * time.Second,
	}
	conn, err := d.DialContext(ctx, "tcp", addr)
	if err != nil {
		return nil, fmt.Errorf("error dialing tcp %s: %w", addr, err)
	}

	// We have a TCP connection; we will force-close it to support context cancellation

	var client *ssh.Client
	finished := make(chan error)
	go func() {
		c, chans, reqs, err := ssh.NewClientConn(conn, addr, f.sshConfig)
		if err == nil {
			client = ssh.NewClient(c, chans, reqs)
			if useBastion {
				err = agent.ForwardToAgent(client, f.keyRing)
				if err != nil {
					err = fmt.Errorf("forwarding ssh auth to keyring: %w", err)
				}
			}
		}

		if err == nil && useBastion {
			session, err := client.NewSession()
			if err != nil {
				finished <- fmt.Errorf("creating ssh session: %w", err)
				return
			}
			defer session.Close()

			err = agent.RequestAgentForwarding(session)
			if err != nil {
				finished <- fmt.Errorf("requesting agent forwarding: %w", err)
				return
			}
		}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Ensure the sshClientFactory is constructed with a valid keyRing (agent.Agent) and that your local ssh-agent is running with the right keys loaded (ssh-add -l)
  2. Verify SSH connectivity/auth to the bastion itself (ssh -A user@bastion) to rule out a broken handshake
  3. If the keyring is intentionally unused, avoid the bastion path (useBastion=false) or fix the factory wiring so keyRing is set

Example fix

// before
factory := &sshClientFactoryImplementation{bastion: bastionHost, sshConfig: cfg} // keyRing missing

// after
keyring := agent.NewKeyring() // or the local agent
factory := &sshClientFactoryImplementation{bastion: bastionHost, sshConfig: cfg, keyRing: keyring}
Defensive patterns

Strategy: try-catch

Validate before calling

if keyRing == nil {
	return fmt.Errorf("keyring must be configured for bastion-routed SSH")
}
out, err := exec.Command("ssh-add", "-l").Output()
if err != nil {
	return fmt.Errorf("no ssh-agent keys available: %w", err)
}

Type guard

func hasKeyRing(f *sshClientFactoryImplementation) bool { return f.keyRing != nil }

Try / catch

client, err := factory.Dial(ctx, host, true)
if err != nil && strings.Contains(err.Error(), "forwarding ssh auth to keyring") {
	return fmt.Errorf("ssh agent forwarding setup failed; check ssh-agent/keys: %w", err)
}

Prevention

When it happens

Trigger: agent.ForwardToAgent(client, f.keyRing) returns an error while establishing a bastion-routed connection — typically because the keyring (agent.Agent) is nil or misconfigured, or the ssh.Client connection broke immediately after handshake.

Common situations: Dumping via bastion when the caller's SSH agent/keyring was not initialized (no keyring passed to the factory); connection to the bastion dropped mid-setup; incompatible agent implementation.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/dc15f8607a4dff33. Report an issue: GitHub.