logconsole

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 6, 2026 License: Apache-2.0 Imports: 25 Imported by: 0

Documentation

Overview

Package logconsole is locklog's console backend for lockkit: the agent's log methods (log.status, log.sources, log.search, log.count, ...), the checks the console makes before it opens a log (the mount roots and the .locklog directory the launcher checked, no network it was not given), the policy of a profile, and the audit record of every call. lockkit's console holds the terminal, the policy review, the approval screens and the audit log; the engine (Engine) reads and masks the logs.

Index

Constants

View Source
const (
	MethodStatus  = "log.status"
	MethodSources = "log.sources"
	MethodSearch  = "log.search"
	MethodCount   = "log.count"
	// MethodPatterns is the top message templates of a range, optionally
	// against a baseline window (locklog_patterns).
	MethodPatterns = "log.patterns"
	// MethodContext, MethodTrace and MethodTail read around a ref, follow
	// an id across sources and follow new records (locklog_context,
	// locklog_trace, locklog_tail).
	MethodContext = "log.context"
	MethodTrace   = "log.trace"
	MethodTail    = "log.tail"
	// MethodScan is a call over the free budgets, approved once (class
	// read) for its whole plan (locklog_scan); MethodUnmask reveals exact
	// pseudonyms of one record on a read-pii approval (locklog_unmask);
	// MethodLookup gives the pseudonyms of clear values, rate-limited
	// (locklog_lookup). Policy changes go through the console's own
	// change.request (locklog_request_change).
	MethodScan   = "log.scan"
	MethodUnmask = "log.unmask"
	MethodLookup = "log.lookup"
)

The agent's methods. Each is free (no approval) within the budgets the engine enforces, and audited.

View Source
const EventCall = "log.call"

Audit events of locklog's calls.

View Source
const SystemFile = "/etc/locklog/system.toml"

SystemFile is the separated setup's file in locklog's image.

Variables

View Source
var ErrConnLost = errors.New("the log session is lost")

ErrConnLost is returned (wrapped) by an engine whose logs can no longer be trusted to be the ones approved (a mount swapped, the engine closed): the console drops the session (console.Env.Lost) and the agent gets ipc.CodeConnLost; the next call reconnects, checking everything again.

View Source
var JournalDirs = []string{"/var/log/journal", "/run/log/journal"}

JournalDirs are the journal directories the launcher binds for a journald source, when they exist on the host.

Methods lists the methods served, in a fixed order.

Functions

func CheckMounts

func CheckMounts(o Options) error

checkMounts compares, in the launcher's container, the device and inode of .locklog and of every mount root with what the launcher checked on the host: a directory swapped (for a link, another directory) between the check and docker run is refused before anything is read.

CheckMounts is exported so that the console command runs it before it reads .locklog at all; LoadPolicy and Connect run it again.

func InImage

func InImage(uid int, stat func(string) (os.FileInfo, error)) bool

InImage reports whether this process runs in locklog's image: as the console account, or with the image's system file present. The console runs only in the launcher's container (or `lox up`'s), which always passes LOCKLOG_EXPECT_DIR: a host holding the system file but started without the launcher is refused, by design.

func Sanitizer

func Sanitizer() *sanitize.Sanitizer

Sanitizer scrubs locklog's error text: URL userinfo and Authorization headers, after the secrets lockkit knows.

func ShowResultsFrom

func ShowResultsFrom(ctx context.Context) bool

ShowResultsFrom reports the clear-results switch of the call.

func WithApprove

func WithApprove(ctx context.Context, a Approve) context.Context

WithApprove attaches the call's approver to ctx.

func WithShowResults

func WithShowResults(ctx context.Context, on bool) context.Context

WithShowResults attaches the console's clear-results switch (Ctrl-O) to ctx: an approval screen then shows its record in clear, on the console, and the engine keeps the call's records for Reveal.

Types

type Approve

type Approve func(ctx context.Context, s console.Screen) console.Approval

Approve asks the human to approve a call's operation on the console's approval screen (console.Env.Approve for the call's request).

func ApproveFrom

func ApproveFrom(ctx context.Context) Approve

ApproveFrom returns the call's approver, or nil.

type Backend

type Backend struct {
	// contains filtered or unexported fields
}

Backend implements console.Backend.

func New

func New(o Options) *Backend

New returns the backend of o.Profile.

func (*Backend) Checks

func (b *Backend) Checks(ctx context.Context, s console.Session) []console.Finding

Checks implements console.Backend: a console with no remote source and no LOCKLOG_NETWORK runs with no network; any interface but the loopback means it was started otherwise, and it refuses.

func (*Backend) Connect

Connect implements console.Backend: the launcher's checks first, then the engine of the policy in force.

func (*Backend) LoadPolicy

func (b *Backend) LoadPolicy() (console.Policy, error)

LoadPolicy implements console.Backend: the profile from the project's .locklog/config.toml with the launch environment.

func (*Backend) Methods

func (b *Backend) Methods() map[string]console.Handler

Methods implements console.Backend.

func (*Backend) Status

func (b *Backend) Status(s console.Session) any

Status implements console.Backend.

type Caller

type Caller struct{ UID, PID int }

Caller is the kernel-verified peer of a call.

type ClearView

type ClearView struct {
	On   bool
	Kept any
}

ClearView is a call's clear-view state: the console's clear-results switch (Ctrl-O) and what the engine keeps for it (its own records).

func ClearViewFrom

func ClearViewFrom(ctx context.Context) *ClearView

ClearViewFrom returns the call's clear-view state, or nil.

type Declined

type Declined struct {
	Resp ipc.Response
}

Declined is an engine's error for a call the human did not approve: Resp is the console's answer (a denial, a timeout, a pending ticket), sent to the agent as is.

func (*Declined) Error

func (d *Declined) Error() string

type Engine

type Engine interface {
	Handle(ctx context.Context, method string, params json.RawMessage, c Caller) (result any, refused *Refusal, err error)
	// Status is the engine's part of log.status and :status.
	Status(ctx context.Context) any
	Close() error
}

Engine answers the agent's log methods. params is the request's raw JSON, validated by the engine; result is a masked, typed value that marshals to JSON. A refusal is the agent's error (over budget, a personal value in a predicate, ...); err is the engine's own failure.

type OpenOptions

type OpenOptions struct {
	// Policy is the approved policy in force: the engine reads only the
	// sources it names.
	Policy config.Policy
	// Credentials are the secret of the profile's remote source (zero for
	// local sources).
	Credentials egress.Credentials
	// StateDir is the console's state directory (home volume).
	StateDir string
	// Roots are the mount roots of the policy's local sources, checked
	// against the launcher's (PlanRoots): the only directories the
	// sources may be given.
	Roots Roots
	// Project is the project root ("" for none): its .locklog holds the
	// human's PII rules.
	Project string
}

OpenOptions is what an engine is opened with.

type Opener

type Opener func(ctx context.Context, o OpenOptions) (Engine, error)

Opener opens the engine of a policy.

type Options

type Options struct {
	Profile string
	// Root is the project root ("" for none).
	Root string
	// StateDir is the console's state base.
	StateDir string
	// Network and ExtraRoots are LOCKLOG_NETWORK and LOCKLOG_EXTRA_ROOTS
	// as the launcher passed them: they are part of the policy.
	Network    string
	ExtraRoots []string
	// ExpectDir and ExpectRoots are LOCKLOG_EXPECT_DIR and
	// LOCKLOG_EXPECT_ROOTS: the device and inode of .locklog and of each
	// mount root, as the launcher checked them on the host.
	ExpectDir   string
	ExpectRoots string
	// DockerRoot is LOCKLOG_DOCKER_ROOT: the containers root the launcher
	// bound for a docker source.
	DockerRoot string
	// InContainer is true in locklog's image (InImage): LOCKLOG_EXPECT_DIR
	// is then required, and Root must be the directory the launcher
	// started the console in.
	InContainer bool
	// SysClassNet is /sys/class/net (tests replace it).
	SysClassNet string
	Open        Opener
}

Options locate the profile a console serves and the launcher's checks.

func FromEnv

func FromEnv(o Options, getenv func(string) string) Options

FromEnv reads the launcher's environment into o. It does not decide InContainer: that is InImage, independent of the variables it checks.

type Policy

type Policy struct {
	config.Policy
}

Policy is a locklog policy as the console handles it.

func (Policy) Diff

func (p Policy) Diff(approved kconfig.Policy) []kconfig.Change

Diff implements config.Policy.

func (Policy) Profile

func (p Policy) Profile() console.Profile

Profile implements console.Policy: the secret the console asks is the one of the profile's remote source (one at most), none for local sources.

type Record

type Record struct {
	audit.Base
	Method  string   `json:"method"`
	Sources []string `json:"sources,omitempty"`
	From    string   `json:"from,omitempty"`
	To      string   `json:"to,omitempty"`
	// Tool is the tool an approved scan runs (log.scan).
	Tool string `json:"tool,omitempty"`
	// Pseudonyms name what an unmask revealed or a lookup resolved, by
	// pseudonym only (never the clear values).
	Pseudonyms []string `json:"pseudonyms,omitempty"`
	// ShownClear counts the records shown in clear on the console's
	// terminal (results on, Ctrl-O), never to the agent.
	ShownClear int `json:"shown_clear,omitempty"`
}

Record is the audit record of one agent call: the method, the sources and the range it named, and the outcome. It never holds a predicate, a value or a log line: those are the agent's and the logs' text, which the detectors may miss.

func (Record) AuditEvent

func (r Record) AuditEvent() string

AuditEvent implements audit.Record.

type Refusal

type Refusal struct {
	Message string
	Info    refusal.Info
}

Refusal is an answer the agent gets as a structured refusal: Message is prose that quotes no value of the agent's call nor of the logs; Info carries the code (E_OVER_BUDGET, E_PII_IN_QUERY, ...), retry and hint.

type Revealer

type Revealer interface {
	Reveal(ctx context.Context, result any) []string
}

Revealer is implemented by an engine that can show the records of a result in clear on the console's terminal (the clear view, Ctrl-O): one line per record, secrets and redactions kept. The lines are never part of an answer to the agent.

type Roots

type Roots struct {
	// Dirs are the directories of the file sources' globs
	// (mountplan.Dir), sorted.
	Dirs []string
	// Journal are the journal directories bound (JournalDirs that
	// exist on the host).
	Journal []string
	// Docker is the containers root (LOCKLOG_DOCKER_ROOT), "" without a
	// docker source.
	Docker string
	// DockerChecked is set when the launcher could stat the containers
	// root from the host and passed its device:inode; usually it cannot
	// (/var/lib/docker is 0710 root), and the root is then the launcher's
	// "not checked from the host" case.
	DockerChecked bool
}

Roots are the mount roots of a policy's local sources, each one the launcher bound and checked (LOCKLOG_EXPECT_ROOTS): the only directories the sources are given.

func PlanRoots

func PlanRoots(o Options, pr config.Profile) (Roots, error)

PlanRoots derives the mount plan of pr (mountplan.Lines) and returns its roots. In the launcher's container (o.InContainer) every planned directory must be one the launcher checked, after CheckMounts passed: a file glob's directory and each journal directory an entry of LOCKLOG_EXPECT_ROOTS, the containers root LOCKLOG_DOCKER_ROOT either such an entry or the launcher's "not checked from the host" case (a clean absolute path ending in /containers, a directory and not a link). A planned root the launcher did not check refuses the policy: the console was not started by the launcher with this plan. Outside the image (a developer's build) nothing was checked, and the planned directories are the roots.

func (Roots) All

func (r Roots) All() []string

All returns every root, sorted.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL