feat(agent): per-agent direct-TLS cert client + HTTPS listener wiring
The agent obtains a valid wildcard cert for *.<hash>.agent.unarr.app from the web broker (ACME DNS-01) so the https web player reaches it directly over HTTPS instead of the CloudFlare funnel. - internal/acme: generate EC P-256 key + CSR locally (private key never leaves the machine), fetch the signed chain from the broker, persist it atomically, NeedsIssue renewal check - daemon: generate + persist a stable agent_hash in config.toml; register before requesting the cert (broker ownership check needs the row); arm the HTTPS listener with the cert; 6h renewal poll hot-swaps it (no restart) - report httpsStreamPort + agentHash on register/sync - stream_server: emit Access-Control-Allow-Private-Network on PNA preflight so an https page can reach the agent on loopback / LAN
This commit is contained in:
parent
3a8c6ddd30
commit
2fcc0d397f
9 changed files with 423 additions and 19 deletions
|
|
@ -79,6 +79,26 @@ func (c *Client) Register(ctx context.Context, req RegisterRequest) (*RegisterRe
|
|||
return &resp, nil
|
||||
}
|
||||
|
||||
// IssueCert sends a CSR to the web-side ACME broker and returns the signed
|
||||
// certificate chain (PEM). The agent's private key never leaves the machine —
|
||||
// only the CSR is sent. Used by the per-agent direct-TLS feature.
|
||||
func (c *Client) IssueCert(ctx context.Context, csrPEM string) (string, error) {
|
||||
req := struct {
|
||||
CSRPem string `json:"csrPem"`
|
||||
}{CSRPem: csrPEM}
|
||||
var resp struct {
|
||||
Certificate string `json:"certificate"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
if err := c.doPost(ctx, "/api/internal/agent/issue-cert", req, &resp); err != nil {
|
||||
return "", fmt.Errorf("issue cert: %w", err)
|
||||
}
|
||||
if resp.Certificate == "" {
|
||||
return "", fmt.Errorf("issue cert: empty certificate (%s)", resp.Error)
|
||||
}
|
||||
return resp.Certificate, nil
|
||||
}
|
||||
|
||||
// Deregister notifies the server that the agent is shutting down.
|
||||
func (c *Client) Deregister(ctx context.Context, agentID string) error {
|
||||
req := struct {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue