agent

package
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Oct 28, 2026 License: Apache-2.0 Imports: 49 Imported by: 0

Documentation

Overview

Package agent is myownpki-agent on a host (docs/PHASE3.md): it enrolls with proof of control (ADR-18), keeps its 7-day agent certificate, and – from block C on – gets certificates by ACME and deploys them.

The agent's only source for what it deploys, where it writes and what it runs is its local agent.yaml: the server never sends a path, a command or a hook name.

Index

Constants

View Source
const (
	DefaultConfigPath = "/etc/myownpki-agent/agent.yaml"
	DefaultStateDir   = "/var/lib/myownpki-agent"
)

DefaultConfigPath and DefaultStateDir are the Linux defaults.

View Source
const (
	ChallengeStandalone = "standalone"
	ChallengeWebroot    = "webroot"
)

Challenge modes for http-01 (owner 2026-10-24).

View Source
const (
	ProfileNginx = "nginx"
	ProfileFile  = "file"
)

Profiles (docs/PHASE3.md step 5).

View Source
const (
	DefaultSetupExampleDir = "/usr/share/myownpki-agent/examples"
)

Variables

View Source
var ErrACMEAccountRegistration = errors.New("ACME account registration requires operator action")

ErrACMEAccountRegistration requires operator action, not a retry with the same key. In particular, a new enrollment has a new agent identity.

View Source
var ErrEnrolled = errors.New("this agent is enrolled and its certificate is valid")

ErrEnrolled: enroll on an agent whose certificate is still valid.

View Source
var ErrInvalid = errors.New("invalid agent configuration")

ErrInvalid wraps every problem of agent.yaml.

Functions

func RenewAt

func RenewAt(leaf *x509.Certificate, r float64) time.Time

RenewAt is when the agent renews its certificate: at 2/3 of the lifetime, up to 10 % of it earlier (r in [0,1) from the caller), so agents enrolled together don't renew together.

func Setup added in v0.3.1

func Setup(ctx context.Context, opts SetupOptions) error

Setup installs local configuration and units, enrolls, and only then enables or starts the service. It never changes host state before preflight succeeds.

func Under

func Under(dirs []string, p string) bool

Under reports whether p lies in one of dirs (lexically, after Clean). At write time the agent also resolves symlinks (see resolveUnder).

Types

type Agent

type Agent struct {

	// Random returns a value in [0,1); tests inject stable independent streams.
	Random func() float64

	// Version, OS, Arch and PackageFormat are reported to the server.
	Version, OS, Arch string
	PackageFormat     string
	// StandaloneAddr is where challenge: standalone listens (":80").
	StandaloneAddr string
	// Now and Sleep: the clock and the wait; tests replace them.
	Now   func() time.Time
	Sleep func(ctx context.Context, d time.Duration) error
	// contains filtered or unexported fields
}

Agent is myownpki-agent.

func New

func New(cfg *Config, log *slog.Logger, version string) (*Agent, error)

New prepares the agent: the state directory, the trust anchor and the channel; the identity on disk, if there is one, becomes the client certificate.

func (*Agent) Enroll

func (a *Agent) Enroll(ctx context.Context, token string) (*Result, error)

Enroll enrolls this host: a new key – or, when its certificate expired, the key of the last certificate (the server knows it then) – a CSR, the check file, the decision. A pending enrollment is kept for `run`.

func (*Agent) Identity

func (a *Agent) Identity() *tls.Certificate

Identity returns the agent's current certificate, or nil.

func (*Agent) Obtain

func (a *Agent) Obtain(ctx context.Context, d Deployment) (*Material, error)

Obtain gets a new certificate by the ordinary ACME path (ADR-19). Scheduled and operator-requested renewals use this same operation.

func (*Agent) Poll

func (a *Agent) Poll(ctx context.Context) (*Result, error)

Poll asks for the decision on the kept enrollment; nil result: none open.

func (*Agent) Recover

func (a *Agent) Recover(ctx context.Context) ([]DeploymentResult, error)

Recover restores one interrupted group before any new ACME/deploy pass. Reload/check failures are reported once; they never start a retry loop.

func (*Agent) Run

func (a *Agent) Run(ctx context.Context) error

Run maintains the agent identity, reports deployment results and follows desired state. Certificate and deployment renewals keep their own schedules.

func (*Agent) RunPass

func (a *Agent) RunPass(ctx context.Context, names []string) ([]DeploymentResult, error)

RunPass renews the named deployments through their local configuration. nil selects all deployments. No request can supply paths or hook names. The runtime calls the same operation for scheduled and requested renewals.

func (*Agent) SetACMEDial

func (a *Agent) SetACMEDial(dial func(context.Context, string, string) (net.Conn, error))

SetACMEDial replaces the ACME network edge for tests. TLS still verifies the directory's host against ca_bundle, with the ordinary HTTP client.

func (*Agent) SetDial

func (a *Agent) SetDial(dial func(ctx context.Context, network, addr string) (net.Conn, error))

SetDial replaces how the agent connects to the server – for tests only (the name in server still is what TLS verifies).

func (*Agent) Status

func (a *Agent) Status() Status

Status reads the state directory.

type Config

type Config struct {
	// Server is agent.base_url of the server, e.g. https://pki.homelab.lan:8444.
	Server string `yaml:"server"`
	// CABundle is the trust anchor (PEM) for the agent listener and ACME.
	CABundle string `yaml:"ca_bundle"`
	// Hostname is the FQDN the agent proves at enrollment; "" = the host's name.
	Hostname string `yaml:"hostname"`
	// ACMEDirectory is the directory URL of any ACME CA.
	ACMEDirectory string `yaml:"acme_directory"`
	// Proxy is an http(s) proxy for both connections; environment variables
	// (HTTPS_PROXY, HTTP_PROXY, NO_PROXY) are never used (owner 2026-10-24).
	Proxy string `yaml:"proxy"`
	// StateDir holds the agent's key, certificate and enrollment.
	StateDir string `yaml:"state_dir"`
	// LogLevel: debug, info, warn, error.
	LogLevel string `yaml:"log_level"`

	Enrollment  Enrollment          `yaml:"enrollment"`
	Hooks       map[string][]string `yaml:"hooks"`
	Paths       []string            `yaml:"paths"`
	Deployments []Deployment        `yaml:"deployments"`
}

Config is agent.yaml.

func LoadConfig

func LoadConfig(path string) (*Config, error)

LoadConfig reads and validates agent.yaml.

func ParseConfig

func ParseConfig(name string, data []byte) (*Config, error)

ParseConfig decodes and validates; name is for messages.

func (*Config) Validate

func (c *Config) Validate() error

Validate checks every rule of docs/PHASE3.md §1.3 and returns all problems at once.

type Deployment

type Deployment struct {
	Name       string   `yaml:"name"`
	Profile    string   `yaml:"profile"`
	Names      []string `yaml:"names"`
	Challenge  string   `yaml:"challenge"`
	Webroot    string   `yaml:"webroot"`
	Dir        string   `yaml:"dir"`
	Files      Files    `yaml:"files"`
	Owner      string   `yaml:"owner"`
	Group      string   `yaml:"group"`
	KeyMode    string   `yaml:"key_mode"`
	TestHook   string   `yaml:"test_hook"`
	ReloadHook string   `yaml:"reload_hook"`
	Check      string   `yaml:"check"`
}

Deployment is one certificate the agent keeps in place (block C).

type DeploymentResult

type DeploymentResult struct {
	Name                  string    `json:"name"`
	State                 string    `json:"state"`
	Serial                string    `json:"serial,omitempty"`
	NotAfter              time.Time `json:"not_after,omitempty"`
	Fingerprint           string    `json:"fingerprint,omitempty"`
	WrittenFingerprint    string    `json:"written_fingerprint,omitempty"`
	CheckConfigured       bool      `json:"check_configured"`
	DeployedAt            time.Time `json:"deployed_at,omitempty"`
	LastError             string    `json:"last_error,omitempty"`
	AttemptedAt           time.Time `json:"attempted_at,omitempty"`
	Failures              int       `json:"failures,omitempty"`
	NextAttempt           time.Time `json:"next_attempt,omitempty"`
	HandledRenewalVersion int64     `json:"handled_renewal_version,omitempty"`
}

DeploymentResult contains only reportable metadata, never key material, hook output, paths or commands. The runtime sends it over Report.

type Enrollment

type Enrollment struct {
	Challenge string `yaml:"challenge"`
	Webroot   string `yaml:"webroot"`
}

Enrollment says how the enrollment check is answered.

type Files

type Files struct {
	Certificate string `yaml:"certificate"`
	Chain       string `yaml:"chain"`
	Fullchain   string `yaml:"fullchain"`
	Key         string `yaml:"key"`
}

Files are the targets of the file profile.

type Material

type Material struct {
	Certificate []byte            `json:"-"`
	Chain       []byte            `json:"-"`
	Fullchain   []byte            `json:"-"`
	Key         []byte            `json:"-"`
	Leaf        *x509.Certificate `json:"-"`
}

Material is an issued certificate and its host-generated key. It is never sent over the agent channel or encoded into a report.

func (*Material) LogValue

func (*Material) LogValue() slog.Value

func (*Material) String

func (*Material) String() string

type Result

type Result struct {
	State   agentv1.EnrollState
	Message string
	AgentID string
}

Result is where an enrollment stands, for the operator.

func (*Result) Admitted

func (r *Result) Admitted() bool

Admitted reports whether the agent has its certificate now.

type SetupOptions added in v0.3.1

type SetupOptions struct {
	Server        string
	CABundle      string
	RootSHA256    string
	TokenFile     string
	Webroot       string
	LowPorts      bool
	Hostname      string
	ConfigPath    string
	StateDir      string
	UnitPath      string
	DropinDir     string
	ExampleDir    string
	Version       string
	PackageFormat string
	Stdout        io.Writer
	Stderr        io.Writer
}

SetupOptions are the local inputs of myownpki-agent setup.

type Status

type Status struct {
	Hostname    string
	AgentID     string
	Enrolled    bool
	NotAfter    time.Time
	Serial      string
	Enrollment  string // the open enrollment's last message
	Deployments []DeploymentResult
}

Status describes the agent for `myownpki-agent status`.

Jump to

Keyboard shortcuts

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