certificate

package
v1.3.7 Latest Latest
Warning

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

Go to latest
Published: Jul 24, 2026 License: AGPL-3.0 Imports: 18 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrMonitorNotFound     = errors.New("certificate monitor not found")
	ErrDuplicateMonitor    = errors.New("hostname:port already monitored")
	ErrAutoDetectedMonitor = errors.New("hostname:port already monitored via endpoint auto-detection")
	ErrInvalidInput        = errors.New("invalid input")
	ErrCannotDeleteAuto    = errors.New("cannot delete auto-detected certificate monitors")
	ErrLimitReached        = errors.New("certificate monitor limit reached")
)

Functions

func DefaultWarningThresholds

func DefaultWarningThresholds() []int

DefaultWarningThresholds returns the default expiration warning thresholds in days.

func ExpiringSeverity added in v1.2.2

func ExpiringSeverity(daysRemaining int, issuerOrg string) string

ExpiringSeverity determines alert severity for an expiring certificate based on days remaining and whether the issuer supports automatic renewal. Auto-renewable certs get lower severity because renewal is expected.

func IsAutoRenewable added in v1.2.2

func IsAutoRenewable(issuerOrg string) bool

IsAutoRenewable returns true if the certificate issuer is known to support automatic renewal (ACME-based CAs like Let's Encrypt).

func IsHTTPS

func IsHTTPS(target string) bool

IsHTTPS isHTTPS checks if a target URL uses the HTTPS scheme.

Types

type CertChainEntry

type CertChainEntry struct {
	ID            string    `json:"id"`
	CheckResultID string    `json:"check_result_id"`
	Position      int       `json:"position"`
	SubjectCN     string    `json:"subject_cn"`
	IssuerCN      string    `json:"issuer_cn"`
	NotBefore     time.Time `json:"not_before"`
	NotAfter      time.Time `json:"not_after"`
}

CertChainEntry represents an individual certificate in the presented chain.

type CertCheckResult

type CertCheckResult struct {
	ID                 string     `json:"id"`
	MonitorID          string     `json:"monitor_id"`
	SubjectCN          string     `json:"subject_cn,omitempty"`
	IssuerCN           string     `json:"issuer_cn,omitempty"`
	IssuerOrg          string     `json:"issuer_org,omitempty"`
	SANs               []string   `json:"sans,omitempty"`
	SerialNumber       string     `json:"serial_number,omitempty"`
	SignatureAlgorithm string     `json:"signature_algorithm,omitempty"`
	NotBefore          *time.Time `json:"not_before,omitempty"`
	NotAfter           *time.Time `json:"not_after,omitempty"`
	ChainValid         *bool      `json:"chain_valid,omitempty"`
	ChainError         string     `json:"chain_error,omitempty"`
	HostnameMatch      *bool      `json:"hostname_match,omitempty"`
	ErrorMessage       string     `json:"error_message,omitempty"`
	CheckedAt          time.Time  `json:"checked_at"`
	OCSPStapled        bool       `json:"ocsp_stapled,omitempty"`
	OCSPStatus         string     `json:"ocsp_status,omitempty"`
	OCSPProducedAt     *time.Time `json:"ocsp_produced_at,omitempty"`
	OCSPNextUpdate     *time.Time `json:"ocsp_next_update,omitempty"`
	OCSPError          string     `json:"ocsp_error,omitempty"`
}

CertCheckResult represents a single certificate check execution.

func (*CertCheckResult) DaysRemaining

func (r *CertCheckResult) DaysRemaining() int

DaysRemaining returns the number of days until the certificate expires. Returns -1 if NotAfter is nil.

func (*CertCheckResult) SANsJSON

func (r *CertCheckResult) SANsJSON() string

SANsJSON returns the JSON-encoded SANs.

type CertMonitor

type CertMonitor struct {
	ID       string `json:"id"`
	Hostname string `json:"hostname"`
	Port     int    `json:"port"`
	// ServerName, when non-empty, is sent as SNI during the check and the
	// certificate is validated against it instead of Hostname.
	ServerName           string     `json:"server_name,omitempty"`
	Source               CertSource `json:"source"`
	EndpointID           *string    `json:"endpoint_id,omitempty"`
	Status               CertStatus `json:"status"`
	CheckIntervalSeconds int        `json:"check_interval_seconds"`
	WarningThresholds    []int      `json:"warning_thresholds"`
	LastAlertedThreshold *int       `json:"last_alerted_threshold,omitempty"`
	LastCheckAt          *time.Time `json:"last_check_at,omitempty"`
	NextCheckAt          *time.Time `json:"next_check_at,omitempty"`
	LastError            string     `json:"last_error,omitempty"`
	ExternalID           string     `json:"external_id,omitempty"`
	CreatedAt            time.Time  `json:"created_at"`
	AgentID              string     `json:"agent_id"`
}

CertMonitor represents a monitored SSL/TLS certificate.

func (*CertMonitor) WarningThresholdsJSON

func (m *CertMonitor) WarningThresholdsJSON() string

WarningThresholdsJSON returns the JSON-encoded warning thresholds.

type CertSource

type CertSource string

CertSource represents how the certificate monitor was created.

const (
	SourceAuto       CertSource = "auto"
	SourceStandalone CertSource = "standalone"
	SourceLabel      CertSource = "label"
)

type CertStatus

type CertStatus string

CertStatus represents the current status of a certificate monitor.

const (
	StatusValid    CertStatus = "valid"
	StatusExpiring CertStatus = "expiring"
	StatusExpired  CertStatus = "expired"
	StatusError    CertStatus = "error"
	StatusUnknown  CertStatus = "unknown"
)

type CertificateStore

type CertificateStore interface {
	// Monitor CRUD
	CreateMonitor(ctx context.Context, m *CertMonitor) (string, error)
	GetMonitorByID(ctx context.Context, id string) (*CertMonitor, error)
	GetMonitorByHostPort(ctx context.Context, hostname string, port int, serverName string) (*CertMonitor, error)
	GetMonitorByHostPortAgent(ctx context.Context, agentID *string, hostname string, port int, serverName string) (*CertMonitor, error)
	GetMonitorByEndpointID(ctx context.Context, endpointID string) (*CertMonitor, error)
	ListMonitors(ctx context.Context, opts ListCertificatesOpts) ([]*CertMonitor, error)
	CountStandaloneMonitors(ctx context.Context) (int, error)
	UpdateMonitor(ctx context.Context, m *CertMonitor) error
	DeleteMonitor(ctx context.Context, id string) error

	// Check results
	InsertCheckResult(ctx context.Context, result *CertCheckResult) (string, error)
	GetLatestCheckResult(ctx context.Context, monitorID string) (*CertCheckResult, error)
	ListCheckResults(ctx context.Context, monitorID string, opts ListChecksOpts) ([]*CertCheckResult, int, error)

	// Chain entries
	InsertChainEntries(ctx context.Context, entries []*CertChainEntry) error
	GetChainEntries(ctx context.Context, checkResultID string) ([]*CertChainEntry, error)

	// Label-discovered monitors
	ListMonitorsByExternalID(ctx context.Context, externalID string) ([]*CertMonitor, error)

	// Scheduler
	ListDueScheduledMonitors(ctx context.Context, now time.Time) ([]*CertMonitor, error)

	// Retention
	DeleteCheckResultsBefore(ctx context.Context, before time.Time, batchSize int) (int64, error)
}

CertificateStore defines the persistence interface for certificate monitoring data.

type ChainCert

type ChainCert struct {
	SubjectCN string
	IssuerCN  string
	NotBefore time.Time
	NotAfter  time.Time
}

ChainCert represents a certificate in the chain.

type CheckCertificateResult

type CheckCertificateResult struct {
	SubjectCN          string
	IssuerCN           string
	IssuerOrg          string
	SANs               []string
	SerialNumber       string
	SignatureAlgorithm string
	NotBefore          time.Time
	NotAfter           time.Time
	ChainValid         bool
	ChainError         string
	HostnameMatch      bool
	Chain              []ChainCert
	Error              string

	OCSPStapled    bool
	OCSPStatus     string
	OCSPProducedAt *time.Time
	OCSPNextUpdate *time.Time
	OCSPError      string
}

CheckCertificateResult holds the raw result of a TLS certificate check.

func CheckCertificate

func CheckCertificate(hostname string, port int, serverName string, timeout time.Duration) *CheckCertificateResult

CheckCertificate performs a TLS handshake to the given hostname:port and extracts certificate details including chain validation. A non-empty serverName is sent as SNI and used for chain validation and hostname matching instead of hostname, so a failover proxy can be checked for the certificate it serves a given vhost.

func CheckCertificateFromPeerCerts

func CheckCertificateFromPeerCerts(certs []*x509.Certificate, hostname string, ocspResponse []byte) *CheckCertificateResult

CheckCertificateFromPeerCerts processes pre-fetched TLS peer certificates (from an HTTP response) without making a new TLS connection.

type CreateCertificateInput

type CreateCertificateInput struct {
	Hostname             string `json:"hostname"`
	Port                 int    `json:"port"`
	ServerName           string `json:"server_name"`
	CheckIntervalSeconds int    `json:"check_interval_seconds"`
	WarningThresholds    []int  `json:"warning_thresholds"`
}

CreateCertificateInput represents the input for creating a standalone certificate monitor.

type DefaultLicenseChecker added in v1.2.2

type DefaultLicenseChecker struct {
	MaxCertificates int
}

DefaultLicenseChecker implements Community edition limits.

func (*DefaultLicenseChecker) CanCreateCertificate added in v1.2.2

func (c *DefaultLicenseChecker) CanCreateCertificate(currentCount int) bool

type Deps added in v1.1.0

type Deps struct {
	Store          CertificateStore // required
	Logger         *slog.Logger     // required
	LicenseChecker LicenseChecker   // optional — defaults to community limits
	EventCallback  EventCallback    // optional — nil-safe
}

Deps holds all dependencies for the certificate Service.

type EventCallback

type EventCallback func(eventType string, data interface{})

EventCallback is called when a certificate event occurs (for SSE broadcasting).

type LicenseChecker added in v1.2.2

type LicenseChecker interface {
	CanCreateCertificate(currentCount int) bool
}

LicenseChecker determines license-gated capabilities for certificate monitors.

type ListCertificatesOpts

type ListCertificatesOpts struct {
	Status string
	Source string
	// AgentFilter filters by agent_id. Nil = no filter; "local" = agent_id IS NULL; UUID = specific agent.
	AgentFilter *string
}

ListCertificatesOpts configures certificate monitor listing queries.

type ListChecksOpts

type ListChecksOpts struct {
	Limit  int
	Offset int
}

ListChecksOpts configures check result listing queries.

type ParsedCertLabel

type ParsedCertLabel struct {
	Hostname string
	Port     int
}

ParsedCertLabel represents a single hostname:port parsed from the TLS certificates label.

func ParseCertificateLabels

func ParseCertificateLabels(labels map[string]string) []ParsedCertLabel

ParseCertificateLabels extracts certificate monitoring targets from container labels. The label format is: maintenant.tls.certificates=host1,host2:8443,host3 Hostnames without a port default to 443.

type Service

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

Service orchestrates certificate monitoring.

func NewService

func NewService(d Deps) *Service

NewService creates a new certificate service.

func (*Service) CountStandaloneMonitors added in v1.2.2

func (s *Service) CountStandaloneMonitors(ctx context.Context) (int, error)

CountStandaloneMonitors returns the count of standalone (manually-added) certificate monitors.

func (*Service) CreateStandalone

func (s *Service) CreateStandalone(ctx context.Context, input CreateCertificateInput) (*CertMonitor, *CertCheckResult, error)

CreateStandalone creates a standalone certificate monitor and runs the first check.

func (*Service) DeleteByEndpointID added in v1.2.5

func (s *Service) DeleteByEndpointID(ctx context.Context, endpointID string)

DeleteByEndpointID removes the auto-detected cert monitor linked to an endpoint.

func (*Service) DeleteMonitor

func (s *Service) DeleteMonitor(ctx context.Context, id string) error

DeleteMonitor removes a standalone certificate monitor and its history.

func (*Service) EnsureAutoDetected

func (s *Service) EnsureAutoDetected(ctx context.Context, endpointID string, targetURL string) (*CertMonitor, error)

EnsureAutoDetected creates or returns the existing auto-detected cert monitor for the given HTTPS endpoint.

func (*Service) GetChainEntries

func (s *Service) GetChainEntries(ctx context.Context, checkResultID string) ([]*CertChainEntry, error)

GetChainEntries returns the chain entries for a check result.

func (*Service) GetLatestCheckResult

func (s *Service) GetLatestCheckResult(ctx context.Context, monitorID string) (*CertCheckResult, error)

GetLatestCheckResult returns the latest check result for a monitor.

func (*Service) GetMonitor

func (s *Service) GetMonitor(ctx context.Context, id string) (*CertMonitor, error)

GetMonitor returns a certificate monitor by ID.

func (*Service) HandleAgentEvent added in v1.3.0

func (s *Service) HandleAgentEvent(ctx context.Context, agentID string, ev *agentpb.CertificateInfo) error

HandleAgentEvent records a TLS certificate scan pushed by a remote agent.

Push-create: the first scan an agent reports for a labelled host provisions the monitor, attributed to that agent. Agent monitors are never dialled by the local scheduler (the host lives on the agent's network, FR-018a) — their state is driven entirely by pushed scans. The result then flows through the same post-check pipeline as a local scan (status, alert evaluation, persistence).

func (*Service) HandleContainerDestroy

func (s *Service) HandleContainerDestroy(ctx context.Context, externalID string)

HandleContainerDestroy removes all label-discovered monitors for a destroyed container.

func (*Service) ListCheckResults

func (s *Service) ListCheckResults(ctx context.Context, monitorID string, opts ListChecksOpts) ([]*CertCheckResult, int, error)

ListCheckResults returns check result history for a monitor.

func (*Service) ListMonitors

func (s *Service) ListMonitors(ctx context.Context, opts ListCertificatesOpts) ([]*CertMonitor, error)

ListMonitors returns all active certificate monitors.

func (*Service) ProcessAutoDetectedCerts

func (s *Service) ProcessAutoDetectedCerts(ctx context.Context, endpointID string, targetURL string, certs []*x509.Certificate, ocspResponse []byte)

ProcessAutoDetectedCerts processes TLS certificates from an HTTP endpoint check.

func (*Service) SetEventCallback

func (s *Service) SetEventCallback(cb EventCallback)

SetEventCallback sets the callback for broadcasting certificate events.

func (*Service) Start

func (s *Service) Start(ctx context.Context)

Start starts a background goroutine that periodically checks standalone certificate monitors that are due for a check.

func (*Service) SyncAgentCerts added in v1.3.0

func (s *Service) SyncAgentCerts(ctx context.Context, agentID, containerExternalID string, labels map[string]string)

SyncAgentCerts provisions label-discovered cert monitors for a REMOTE agent's container. Mirrors SyncFromLabels but attributes monitors to agentID; those are never dialled by the local scheduler (ListDueScheduledMonitors skips agent_id IS NOT NULL) — the agent scans them and pushes results. Reconciles removed labels (FR-018a).

func (*Service) SyncFromLabels

func (s *Service) SyncFromLabels(ctx context.Context, containerExternalID string, labels map[string]string)

SyncFromLabels reconciles label-discovered certificate monitors for a container. It creates new monitors for hostnames present in labels, and removes monitors for hostnames that were removed from labels.

func (*Service) UpdateMonitor

func (s *Service) UpdateMonitor(ctx context.Context, id string, input UpdateCertificateInput) (*CertMonitor, error)

UpdateMonitor updates a certificate monitor's settings.

type UpdateCertificateInput

type UpdateCertificateInput struct {
	CheckIntervalSeconds *int  `json:"check_interval_seconds,omitempty"`
	WarningThresholds    []int `json:"warning_thresholds,omitempty"`
}

UpdateCertificateInput represents the input for updating a certificate monitor.

Jump to

Keyboard shortcuts

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