a73x

internal/cli/pin.go

Ref:   Size: 1.3 KiB   History

package cli

import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"golang.org/x/crypto/ssh"

	"github.com/a73x/eitri/internal/server/api/client"
)

// WriteHostCAPin fetches eitri's host-CA public key (public endpoint) and
// overwrites pinPath with the single `@cert-authority *` line. A dedicated
// file, never the user's main known_hosts: a wildcard cert authority there
// would trust eitri's CA for every host the user sshes to.
func WriteHostCAPin(ctx context.Context, baseURL, pinPath string) error {
	c := &client.Client{BaseURL: baseURL}
	line, err := c.FetchSSHCALine(ctx)
	if err != nil {
		return err
	}
	// The client already parse-validated the line; this re-parse feeds the
	// canonical re-marshal — one clean line whatever whitespace arrived —
	// while preserving the server's comment (e.g. "eitri-host-ca").
	caKey, comment, _, _, err := ssh.ParseAuthorizedKey([]byte(line))
	if err != nil {
		return fmt.Errorf("fetch host CA: not an SSH public key: %w", err)
	}
	if err := os.MkdirAll(filepath.Dir(pinPath), 0o700); err != nil {
		return err
	}
	marshaled := strings.TrimSpace(string(ssh.MarshalAuthorizedKey(caKey)))
	var pin string
	if comment != "" {
		pin = "@cert-authority * " + marshaled + " " + comment + "\n"
	} else {
		pin = "@cert-authority * " + marshaled + "\n"
	}
	return os.WriteFile(pinPath, []byte(pin), 0o644)
}