package osupdate // The root step that keeps a readable copy of Proxmox's root CA for the agent (R-1380, D80, felhom.eu `03` §12a). // The rule lives in the wrapper (mode pve-ca-copy: one fixed source, one fixed place, a CA certificate only); the plan // names nothing. internal/pvetrust decides when to ask and what to do with the answer. import ( "context" "encoding/json" "fmt" ) // PVECACopyPath is where the wrapper puts the copy (felhom-os-apply PVE_CA_COPY) — the agent's `proxmox.tls.ca_file`. const PVECACopyPath = "/etc/felhom-agent/pve-root-ca.pem" // PVECACopyResult is the wrapper's pve_ca_copy object. type PVECACopyResult struct { Outcome string `json:"outcome"` // written | same Path string `json:"path"` SHA256 string `json:"sha256"` NotAfter string `json:"not_after"` DaysLeft int `json:"days_left"` Replaced bool `json:"replaced"` } // PVECACopy asks the wrapper to make or refresh the copy. An error names a refusal (T1–T3, or R11 from a wrapper that // does not know the mode yet) or a wrapper that gave no answer. func (l *Leg) PVECACopy(ctx context.Context) (PVECACopyResult, error) { wr, err := l.call(ctx, "pveca"+l.now().UTC().Format("150405.000"), map[string]any{"release_id": "pve-ca-copy", "layer": LayerHost, "mode": "pve-ca-copy"}) if err != nil { return PVECACopyResult{}, err } if wr.refused() { return PVECACopyResult{}, fmt.Errorf("pve-ca-copy refused: %s", wr.Refused) } if wr.failed() { return PVECACopyResult{}, fmt.Errorf("pve-ca-copy failed: %s", wr.Failed) } var res PVECACopyResult if jerr := json.Unmarshal(wr.PVECACopy, &res); jerr != nil || res.Outcome == "" || res.Path == "" { return PVECACopyResult{}, fmt.Errorf("pve-ca-copy: the wrapper gave no result (%v)", jerr) } return res, nil }