feat(agent-go): consume panel-hosted Reality keys (persist keyMaterial, backfill unused-provided keys)
This commit is contained in:
+71
-1
@@ -92,7 +92,12 @@ func realityKey(keyID string) (realityKeyPair, error) {
|
||||
}
|
||||
|
||||
type artifacts struct {
|
||||
RealityPublicKey *string `json:"realityPublicKey,omitempty"`
|
||||
RealityPublicKey *string `json:"realityPublicKey,omitempty"`
|
||||
KeyMaterial map[string]realityKeyPair `json:"keyMaterial,omitempty"`
|
||||
// used records every keypair resolved during materialize (never
|
||||
// serialized); applyResourceLocked diffs it against the payload-provided
|
||||
// keys to compute the backfill reported to the panel.
|
||||
used map[string]realityKeyPair
|
||||
}
|
||||
|
||||
func (a *artifacts) toMap() map[string]interface{} {
|
||||
@@ -100,6 +105,67 @@ func (a *artifacts) toMap() map[string]interface{} {
|
||||
if a.RealityPublicKey != nil {
|
||||
out["realityPublicKey"] = *a.RealityPublicKey
|
||||
}
|
||||
if len(a.KeyMaterial) > 0 {
|
||||
out["keyMaterial"] = a.KeyMaterial
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// persistKeyMaterial merges panel-provided keypairs into keys.json before a
|
||||
// resource is materialized. The panel is the source of truth: a provided
|
||||
// pair replaces a divergent local entry, so a node restored from the panel
|
||||
// store converges back to the hosted keypair. keys.json stays 0600 (saveKeys).
|
||||
func persistKeyMaterial(material map[string]realityKeyPair) error {
|
||||
if len(material) == 0 {
|
||||
return nil
|
||||
}
|
||||
keys, err := loadKeys()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
changed := false
|
||||
for keyID, pair := range material {
|
||||
if pair.PrivateKey == "" || pair.PublicKey == "" {
|
||||
continue
|
||||
}
|
||||
stored := pair
|
||||
if raw, ok := keys[keyID]; ok {
|
||||
var existing realityKeyPair
|
||||
if err := json.Unmarshal(raw, &existing); err == nil {
|
||||
if existing.PrivateKey == pair.PrivateKey && existing.PublicKey == pair.PublicKey {
|
||||
continue
|
||||
}
|
||||
if stored.CreatedAt == "" {
|
||||
stored.CreatedAt = existing.CreatedAt
|
||||
}
|
||||
}
|
||||
}
|
||||
if stored.CreatedAt == "" {
|
||||
stored.CreatedAt = isoNow()
|
||||
}
|
||||
encoded, err := json.Marshal(stored)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keys[keyID] = encoded
|
||||
changed = true
|
||||
}
|
||||
if !changed {
|
||||
return nil
|
||||
}
|
||||
return saveKeys(keys)
|
||||
}
|
||||
|
||||
// backfillKeyMaterial returns the keypairs this apply actually used that the
|
||||
// panel did not provide in the payload. The panel stores them on job
|
||||
// completion, so keys that predate panel hosting migrate into the store.
|
||||
func backfillKeyMaterial(used, provided map[string]realityKeyPair) map[string]realityKeyPair {
|
||||
out := map[string]realityKeyPair{}
|
||||
for keyID, pair := range used {
|
||||
if _, ok := provided[keyID]; !ok {
|
||||
out[keyID] = pair
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
@@ -141,6 +207,10 @@ func materialize(value interface{}, art *artifacts) (interface{}, error) {
|
||||
}
|
||||
pub := pair.PublicKey
|
||||
art.RealityPublicKey = &pub
|
||||
if art.used == nil {
|
||||
art.used = map[string]realityKeyPair{}
|
||||
}
|
||||
art.used[match[1]] = pair
|
||||
return pair.PrivateKey, nil
|
||||
default:
|
||||
return value, nil
|
||||
|
||||
Reference in New Issue
Block a user