Charm architecture¶
The osquery charm is a subordinate machine charm. Rather than running a workload
in a container, it installs and manages the osqueryd daemon directly on the
principal’s machine as the c-osquery snap, managed through snapd.
Architecture overview¶
The osquery charm is a machine charm, so it is not containerized: there is no OCI
image and no Pebble services. Both the Juju unit agent (which runs the charm code) and the
osqueryd workload it manages run directly on the principal’s host, sharing
the same machine as the principal unit. The charm’s only moving parts are the
charm code, the osqueryd snap service, and the files the charm writes
under /var/snap/c-osquery/common/etc/osquery.
flowchart TB
subgraph machine["Principal machine (no container)"]
principal["Principal unit"]
subgraph agent["Juju unit agent"]
charm["osquery charm code<br/>(charm.py reconcile)"]
end
osqueryd["osqueryd<br/>(c-osquery snap service)"]
subgraph files["/var/snap/c-osquery/common/etc/osquery"]
flagfile["osquery.flags"]
secrets["enroll.secret<br/>TLS certificates"]
end
principal -.->|osquery:general-info| charm
charm -->|installs & manages| osqueryd
charm -->|writes| flagfile
charm -->|writes| secrets
osqueryd -->|reads| flagfile
osqueryd -->|reads| secrets
end
controller["osquery controller"]
osqueryd -->|TLS: enroll / config / logs| controller
Workload¶
The charm installs the Canonical SecOps fork of osquery from the c-osquery
snap, with classic confinement, from the channel set in snap-channel. Once
installed, osquery runs as the snap’s c-osquery.osqueryd service (the
snap.c-osquery.osqueryd.service systemd unit). The daemon
reads its command-line flags from a flagfile on disk; the charm generates this
flagfile from the Juju configuration, so changing a configuration value and
restarting the daemon is how the charm applies changes to the workload.
The agent connects outward over TLS to a centrally managed osquery controller, which supplies its configuration (query schedules, telemetry rules, and query tasks) and collects its logs.
Reconcile pattern¶
The charm follows a holistic reconcile pattern. A single handler,
_reconcile, is observed on every relevant lifecycle event —
install, upgrade-charm, start, config-changed,
secret-changed, and update-status. On each event the handler:
Ensures the osquery snap is installed and tracks the configured
snap-channel, installing or refreshing it if it doesn’t.Renders the current Juju configuration into the osquery flagfile and writes the file-backed secrets (the enrollment secret and TLS material) to disk.
Restarts the
osqueryddaemon if necessary.Reports the resulting unit status.
Because the handler is idempotent, it’s safe to run on every event. If a required
configuration value is missing or invalid, the charm sets a blocked status
with a descriptive message instead of failing the hook. The stop event is
handled separately to clean up the workload when the unit is removed.
flowchart TD
event["Lifecycle event<br/>(install, config-changed, ...)"] --> reconcile["_reconcile"]
reconcile --> installed{"Snap installed<br/>on channel?"}
installed -->|no| install["Install or refresh snap"]
installed -->|yes| render["Render flagfile<br/>+ write secrets"]
install --> render
render --> valid{"Config<br/>valid?"}
valid -->|no| blocked["Set blocked status"]
valid -->|yes| restart["Restart osqueryd<br/>if config changed"]
restart --> active["Set active status"]
Code structure¶
The charm is organized into focused modules that separate the Juju-facing logic from the host-facing logic:
Module |
Responsibility |
|---|---|
|
The |
|
Host workload management: installing, refreshing, and removing the
|
|
Translates Juju configuration values into the osquery flagfile and determines which required options are unset. |
|
The charm’s exception hierarchy, including |
Juju integration¶
As a subordinate, the charm attaches to a principal application through the
general-info relation (interface juju-info, container scope). This
places one osquery unit on each principal machine. See Relation endpoints for details.
For the configuration options that drive the flagfile, see Configurations. For the events the charm observes, see Juju events.