Documentation
¶
Overview ¶
Package agentstate owns the agent's per-instance state directory: the stable instance ID (R31) and the remote configuration cache (R7).
Layout (the OCI download caches under .compliance-framework/{plugins,policies} are shared and unchanged):
.compliance-framework/state/<key>/ key = hex(sha256(abs config path))[:16]; dir 0700 instance-id 0644, UUID + "\n" remote-config.json 0600
The package is a leaf: it never imports cmd.
Index ¶
Constants ¶
const ( // StateRoot is the default parent of every per-config state directory, relative to the // working directory like the download caches. StateRoot = ".compliance-framework/state" )
Variables ¶
var ErrCacheCorrupt = errors.New("remote config cache corrupt")
ErrCacheCorrupt is returned by LoadCache when the cache file does not parse or its checksum does not match. The agent reports failed/cache-corrupt once and continues without the cache.
Functions ¶
func CanonicalOverlay ¶
func CanonicalOverlay(raw json.RawMessage) (json.RawMessage, error)
CanonicalOverlay returns raw in the form a save/load round trip of the cache yields: compact, with <, > and & escaped as encoding/json escapes them. SaveCache re-indents the overlay and LoadCache would otherwise return those re-indented bytes, so anything that hashes or compares overlay bytes (the no-ETag rejection key) must use this form, for a fresh 200 body as well as a cached one. An empty overlay is returned unchanged.
func DefaultDir ¶
DefaultDir returns the default state directory for a config file: StateRoot/<key>, where key is the first 16 hex characters of sha256 of the absolute config path. Moving or renaming the config file therefore changes the directory and the instance ID (R52); containers should pin CCF_STATE_DIR.
Types ¶
type Cache ¶
type Cache struct {
Version int `json:"version"`
Identity Identity `json:"identity"`
Applied *OverlayRecord `json:"applied,omitempty"`
Fetched *OverlayRecord `json:"fetched,omitempty"` // newest 200 body; may be the rejected one
Rejected *RejectedRecord `json:"rejected,omitempty"`
Checksum string `json:"checksum"` // sha256 of the JSON with Checksum = ""
}
Cache is the persisted remote configuration state (0600, it may hold values an admin typed).
func (*Cache) IfNoneMatch ¶
IfNoneMatch is the ETag to present on the next fetch: the last 200's raw ETag, falling back to the applied one, or "" for an unconditional fetch.
type Identity ¶
Identity binds a cache to the API and credentials it was fetched with (R7). A cache whose identity differs from the current one is discarded, so a new client_id or API URL never applies another agent's overlay.
type OverlayRecord ¶
type OverlayRecord struct {
Revision int64 `json:"revision"`
// ETag is the RAW ETag header of the 200 response (opaque, e.g. "r<rev>-<uuid>"). It is
// sent back verbatim as If-None-Match and never built from a revision number (R7).
ETag string `json:"etag"`
Overlay json.RawMessage `json:"overlay"`
FetchedAt time.Time `json:"fetched_at"`
}
OverlayRecord is one overlay document received from the API.
type RejectedRecord ¶
type RejectedRecord struct {
Revision int64 `json:"revision"`
ETag string `json:"etag"`
// OverlaySHA256 keys the record with the revision when the response had no ETag.
OverlaySHA256 string `json:"overlay_sha256,omitempty"`
BaseFingerprint string `json:"base_fingerprint"`
Status string `json:"status"`
Reason string `json:"reason"`
Error string `json:"error"`
// Unsafe completes the outcome re-reported after a restart. It is optional: caches
// written before it existed load (and checksum) unchanged.
Unsafe []agentconfig.Change `json:"unsafe,omitempty"`
}
RejectedRecord remembers that a fetched overlay was rejected against a given base, so it is not re-prepared on every poll. It is keyed by (ETag, BaseFingerprint); the revision is informational only because a reset API can reuse revision numbers, except when the response carried no ETag: then (Revision, OverlaySHA256) stands in for it.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is one agent instance's state directory. A Store whose directory is not writable keeps working in memory: the agent never fails because it cannot persist state.
func Open ¶
Open prepares dir (MkdirAll 0700) and probes that it is writable. A failure is logged once as a WARN and the store continues in memory; it is never fatal.
func (*Store) InstanceID ¶
InstanceID returns this instance's stable ID and whether it is persisted:
- a valid override (flag or CCF_INSTANCE_ID) wins and is not persisted;
- otherwise the instance-id file;
- otherwise a new ID, written atomically (a corrupt file is replaced);
- if the store is not writable, the new ID lives in memory only (one WARN).
The result is memoized: every call on one Store returns the same ID.
func (*Store) LoadCache ¶
LoadCache reads the cache for identity id. A missing file yields an empty cache. A corrupt file yields an empty cache and ErrCacheCorrupt. A cache bound to another identity is discarded (empty cache, nil error, one INFO). Overlays are returned in CanonicalOverlay form.