Documentation
¶
Index ¶
- Constants
- Variables
- func CleanDBEngines(in []string) []string
- func JobAllowedOnAgent(jobType, agentType string) bool
- func NormalizeAgentType(t string) (string, bool)
- func NormalizeJobType(t string) (string, bool)
- func SetScheduleLocation(loc *time.Location)
- func ValidateBackupPaths(paths []string) ([]string, error)
- func ValidateBackupPathsFor(agentOS string, paths []string) ([]string, error)
- func ValidateCron(expr string) error
- func ValidateExcludePatterns(patterns []string) error
- func ValidateLabels(l Labels) error
- func ValidateLocalBackupPaths(paths []string) ([]string, error)
- type APIKey
- type Agent
- type AgentAuthState
- type AgentCapabilities
- type AgentStatus
- type AuditEntry
- type AuditFilter
- type BackupJob
- func (j *BackupJob) EffectiveBackupID() string
- func (j *BackupJob) IsDatabase() bool
- func (j *BackupJob) IsDocker() bool
- func (j *BackupJob) IsKubernetes() bool
- func (j *BackupJob) IsM365() bool
- func (j *BackupJob) IsPVE() bool
- func (j *BackupJob) NextRunString() string
- func (j *BackupJob) Sanitize() *BackupJob
- func (j *BackupJob) Summary() string
- type BackupRun
- type BackupTarget
- type DB
- func (d *DB) BindTokenAgent(ctx context.Context, tokenID, agentID uuid.UUID) error
- func (d *DB) BindingsFor(ctx context.Context, email string, groups, claims []string) ([]*RoleBinding, error)
- func (d *DB) BootstrapAdmin(ctx context.Context, email, role string) (bool, error)
- func (d *DB) BumpAgentTokenVersion(ctx context.Context, id uuid.UUID) (int, error)
- func (d *DB) ClearAgentUpdateRequest(ctx context.Context, id uuid.UUID) error
- func (d *DB) CloneTarget(ctx context.Context, sourceID uuid.UUID, name, namespace, pxarFormat string) (*BackupTarget, error)
- func (d *DB) Close()
- func (d *DB) CountRunsWithKey(ctx context.Context, fingerprint string) (int, error)
- func (d *DB) CreateAPIKey(ctx context.Context, key *APIKey) error
- func (d *DB) CreateAgent(ctx context.Context, agent *Agent) error
- func (d *DB) CreateBinding(ctx context.Context, b *RoleBinding) error
- func (d *DB) CreateEnrollmentToken(ctx context.Context, token *EnrollmentToken) error
- func (d *DB) CreateJob(ctx context.Context, job *BackupJob) error
- func (d *DB) CreateKeyRing(ctx context.Context, r *KeyRing) error
- func (d *DB) CreateRole(ctx context.Context, r *Role) error
- func (d *DB) CreateRun(ctx context.Context, run *BackupRun) error
- func (d *DB) CreateTarget(ctx context.Context, target *BackupTarget) error
- func (d *DB) CreateTargetKey(ctx context.Context, k *TargetKey) error
- func (d *DB) CreateTenant(ctx context.Context, t *m365.Tenant) error
- func (d *DB) DeleteAgent(ctx context.Context, id uuid.UUID) error
- func (d *DB) DeleteBinding(ctx context.Context, id uuid.UUID) error
- func (d *DB) DeleteEnrollmentToken(ctx context.Context, id uuid.UUID) error
- func (d *DB) DeleteJob(ctx context.Context, id uuid.UUID) error
- func (d *DB) DeleteKeyRing(ctx context.Context, id uuid.UUID) error
- func (d *DB) DeleteRole(ctx context.Context, name string) error
- func (d *DB) DeleteTarget(ctx context.Context, id uuid.UUID) error
- func (d *DB) DeleteTenant(ctx context.Context, id uuid.UUID) error
- func (d *DB) EnsureUnlimitedEnrollmentToken(ctx context.Context, tokenHash, name string) error
- func (d *DB) GetAPIKeyByHash(ctx context.Context, hash string) (*APIKey, error)
- func (d *DB) GetAgentAuthState(ctx context.Context, id uuid.UUID) (*AgentAuthState, error)
- func (d *DB) GetAgentByID(ctx context.Context, id uuid.UUID, scope Scope) (*Agent, error)
- func (d *DB) GetBinding(ctx context.Context, id uuid.UUID) (*RoleBinding, error)
- func (d *DB) GetEnrollmentToken(ctx context.Context, id uuid.UUID, scope Scope) (*EnrollmentToken, error)
- func (d *DB) GetJobByID(ctx context.Context, id uuid.UUID, scope Scope) (*BackupJob, error)
- func (d *DB) GetKeyRing(ctx context.Context, id uuid.UUID, scope Scope) (*KeyRing, error)
- func (d *DB) GetRole(ctx context.Context, name string) (*Role, error)
- func (d *DB) GetRunByID(ctx context.Context, id uuid.UUID, scope Scope) (*BackupRun, error)
- func (d *DB) GetRunByWorkflowID(ctx context.Context, workflowID string) (*BackupRun, error)
- func (d *DB) GetTargetByID(ctx context.Context, id uuid.UUID, scope Scope) (*BackupTarget, error)
- func (d *DB) GetTargetKey(ctx context.Context, id uuid.UUID) (*TargetKey, error)
- func (d *DB) GetTenantByID(ctx context.Context, id uuid.UUID, scope Scope) (*m365.Tenant, error)
- func (d *DB) HasSealedSecrets(ctx context.Context) (bool, error)
- func (d *DB) LatestRunByJob(ctx context.Context) (map[uuid.UUID]*JobLastRun, error)
- func (d *DB) ListAPIKeys(ctx context.Context) ([]*APIKey, error)
- func (d *DB) ListAgents(ctx context.Context, scope Scope) ([]*Agent, error)
- func (d *DB) ListAudit(ctx context.Context, f AuditFilter, scope Scope) ([]*AuditEntry, error)
- func (d *DB) ListBindings(ctx context.Context) ([]*RoleBinding, error)
- func (d *DB) ListEnrollmentTokens(ctx context.Context, scope Scope) ([]*EnrollmentToken, error)
- func (d *DB) ListJobs(ctx context.Context, scope Scope) ([]*BackupJob, error)
- func (d *DB) ListKeyRings(ctx context.Context, scope Scope) ([]*KeyRing, error)
- func (d *DB) ListRingKeys(ctx context.Context, ringID uuid.UUID) ([]*TargetKey, error)
- func (d *DB) ListRoles(ctx context.Context) ([]*Role, error)
- func (d *DB) ListRuns(ctx context.Context, limit int, scope Scope) ([]*BackupRun, error)
- func (d *DB) ListRunsByAgent(ctx context.Context, agentID uuid.UUID, limit int, scope Scope) ([]*BackupRun, error)
- func (d *DB) ListSeenSubjects(ctx context.Context) ([]*SeenSubject, error)
- func (d *DB) ListTargets(ctx context.Context, scope Scope) ([]*BackupTarget, error)
- func (d *DB) ListTenants(ctx context.Context, scope Scope) ([]*m365.Tenant, error)
- func (d *DB) MarkRunStarted(ctx context.Context, id uuid.UUID, temporalRunID string, startedAt time.Time) error
- func (d *DB) MergeAgents(ctx context.Context, from, into uuid.UUID) (int64, int64, error)
- func (d *DB) Migrate(ctx context.Context) error
- func (d *DB) PruneAudit(ctx context.Context, before time.Time, export func([]*AuditEntry) error) (int, error)
- func (d *DB) RecordSignIn(ctx context.Context, email string, groups, claims []string) error
- func (d *DB) RequestAgentUpdate(ctx context.Context, id uuid.UUID) error
- func (d *DB) RetireTargetKey(ctx context.Context, id uuid.UUID) error
- func (d *DB) RevokeAPIKey(ctx context.Context, id uuid.UUID) error
- func (d *DB) RevokeAgent(ctx context.Context, id uuid.UUID) error
- func (d *DB) ScopedBindingsOfRole(ctx context.Context, role string) (int, error)
- func (d *DB) SealLegacySecrets(ctx context.Context) (int, error)
- func (d *DB) SetAgentAutoUpdate(ctx context.Context, id uuid.UUID, enabled bool) error
- func (d *DB) SetAgentDebugLogging(ctx context.Context, id uuid.UUID, enabled bool) error
- func (d *DB) SetAgentInventoryDetail(ctx context.Context, id uuid.UUID, detail []byte) error
- func (d *DB) SetAgentLabels(ctx context.Context, id uuid.UUID, labels Labels) error
- func (d *DB) SetRingActiveKey(ctx context.Context, ringID uuid.UUID, keyID *uuid.UUID) error
- func (d *DB) SetRunItems(ctx context.Context, runID uuid.UUID, updatedAt string, ...) error
- func (d *DB) SetRunPhase(ctx context.Context, runID uuid.UUID, phase, updatedAt string) error
- func (d *DB) SetRunStatus(ctx context.Context, id uuid.UUID, status RunStatus, message string, ...) error
- func (d *DB) SetTargetEncryption(ctx context.Context, targetID uuid.UUID, mode string, ringID *uuid.UUID) error
- func (d *DB) SetTargetTokenCheck(ctx context.Context, id uuid.UUID, check *pbs.TokenCheck) (string, error)
- func (d *DB) SyncBuiltinRoles(ctx context.Context, roles map[string][]string, descriptions map[string]string) error
- func (d *DB) TouchAPIKey(ctx context.Context, id uuid.UUID) error
- func (d *DB) UpdateAgentHeartbeat(ctx context.Context, id uuid.UUID, status AgentStatus, caps AgentCapabilities) (HeartbeatState, error)
- func (d *DB) UpdateJob(ctx context.Context, job *BackupJob) error
- func (d *DB) UpdateKeyRing(ctx context.Context, r *KeyRing) error
- func (d *DB) UpdateRole(ctx context.Context, r *Role) error
- func (d *DB) UpdateRun(ctx context.Context, run *BackupRun) error
- func (d *DB) UpdateTarget(ctx context.Context, target *BackupTarget) error
- func (d *DB) UpdateTenant(ctx context.Context, t *m365.Tenant) error
- func (d *DB) UpsertAgent(ctx context.Context, agent *Agent) error
- func (d *DB) ValidateAndConsumeToken(ctx context.Context, tokenHash string) (*EnrollmentToken, error)
- func (d *DB) WriteAudit(ctx context.Context, e *AuditEntry) error
- type EnrollmentToken
- type HeartbeatState
- type JobLastRun
- type KeyRing
- type Labels
- type Migration
- type Requirement
- type Role
- type RoleBinding
- type RunStatus
- type Scope
- type SeenSubject
- type Selector
- type TargetKey
Constants ¶
const ( AgentTypeFilesystem = config.AgentTypeFilesystem AgentTypeDatabase = config.AgentTypeDatabase AgentTypeKubernetes = config.AgentTypeKubernetes JobTypeFilesystem = config.AgentTypeFilesystem JobTypeDatabase = config.AgentTypeDatabase JobTypeKubernetes = config.AgentTypeKubernetes // JobTypePVE backs up a Proxmox VE host's configuration; it runs on the // filesystem agent installed on the node JobTypePVE = "pve" // JobTypeDocker backs up a Docker host (definitions, compose files, volumes); it // runs on the filesystem agent installed on the host JobTypeDocker = "docker" // JobTypeM365 backs up a Microsoft 365 tenant through Graph; it runs on any // filesystem agent with outbound HTTPS (no host capability involved) JobTypeM365 = "m365" )
Agent / job types: each agent binary handles one kind of job
const ( PxarFormatV1 = "v1" // single stream + catalog; browsable everywhere PxarFormatV2 = "v2" // split metadata/payload streams; PBS 3.2+ )
pxar archive formats a target accepts
const ( EncryptionNone = "none" EncryptionEncrypt = "encrypt" )
Encryption modes of a target
const ( BindingUser = "user" BindingGroup = "group" // BindingClaim matches a value of a configured ID token claim; the subject is // "<claim>=<value>" (e.g. roles=Backup.Admin) BindingClaim = "claim" )
Binding kinds
const ( OpIn = "in" // key=v, key==v, key in (v1, v2) OpNotIn = "notin" // key!=v, key notin (v1, v2): also matches when key is absent OpExists = "exists" // key OpNotExists = "!" // !key )
Selector operators
const MaxLabels = 20
MaxLabels caps the entries on one object or selector
const StaleAfter = 90 * 24 * time.Hour
StaleAfter is how long a binding's subject may go unseen at sign-in before the Access page flags it
Variables ¶
var ( ErrNotFound = errors.New("record not found") // ErrInUse: the row is referenced by others and cannot be deleted ErrInUse = errors.New("record is in use") )
var ErrLastAdmin = errors.New("this is the last binding that grants rbac:manage on everything")
ErrLastAdmin refuses removing the last binding that can manage access
var ErrTenantInUse = errors.New("tenant is referenced by backup jobs")
ErrTenantInUse is returned when a tenant still has jobs
var Unscoped = Scope{All: true}
Unscoped reaches every row. Only for internal callers (workflows, agent endpoints, the PBS tunnel); admin requests take their scope from the principal.
Functions ¶
func CleanDBEngines ¶ added in v0.11.3
CleanDBEngines keeps the known engine names, canonical and without duplicates
func JobAllowedOnAgent ¶ added in v0.9.5
JobAllowedOnAgent reports whether an agent of agentType may run a job of jobType. Job types normally match the agent type; the exceptions are database jobs on a kubernetes agent (dumped from a pod inside the cluster) or on a filesystem agent (the combined agent, when it reports database client tools), Proxmox VE / Docker host jobs, which run on the filesystem agent installed on the host, and Microsoft 365 jobs, which any filesystem agent runs.
func NormalizeAgentType ¶ added in v0.6.0
NormalizeAgentType maps "" to filesystem and reports unknown values
func NormalizeJobType ¶ added in v0.9.5
NormalizeJobType maps "" to filesystem and accepts the job-only types pve, docker and m365
func SetScheduleLocation ¶ added in v0.7.2
SetScheduleLocation installs the timezone used for next-run display
func ValidateBackupPaths ¶ added in v0.6.0
ValidateBackupPaths normalises a job's backup paths and rejects combinations that cannot form one archive: every path must be absolute, exact duplicates are dropped and no path may lie inside another (its data would be archived twice). Paths sharing a basename are fine; the agent names them after their full path in the archive. The rules are those of a Unix agent regardless of the host the server runs on, so the slash-only path package is used rather than path/filepath.
func ValidateBackupPathsFor ¶ added in v0.9.5
ValidateBackupPathsFor validates paths with the rules of the agent's operating system ("windows" or anything else): the server runs on Linux but stores jobs for Windows agents, whose paths use drive letters and backslashes.
func ValidateCron ¶ added in v0.6.2
ValidateCron rejects schedule expressions the scheduler cannot run; empty = manual
func ValidateExcludePatterns ¶ added in v0.6.0
ValidateExcludePatterns checks exclude patterns against the pxar pattern syntax (proxmox-backup-client --exclude); invalid patterns would otherwise fail the backup only at run time on the agent.
func ValidateLabels ¶ added in v1.0.0
ValidateLabels applies the Kubernetes label syntax: key is [prefix/]name with a DNS subdomain prefix (at most 253 characters) and a name of at most 63 characters; the value is empty or a name. At most MaxLabels entries.
func ValidateLocalBackupPaths ¶ added in v0.9.6
ValidateLocalBackupPaths validates paths with the rules of the operating system the caller runs on; the agent uses it for the paths it is about to read.
Types ¶
type APIKey ¶
type APIKey struct {
ID uuid.UUID `json:"id"`
Name string `json:"name"`
KeyHash string `json:"-"`
CreatedBy string `json:"created_by"`
CreatedAt time.Time `json:"created_at"`
LastUsedAt *time.Time `json:"last_used_at"`
ExpiresAt *time.Time `json:"expires_at"`
RevokedAt *time.Time `json:"revoked_at"`
// Role and Selector are the key's single access binding
Role string `json:"role"`
Selector Selector `json:"selector"`
}
APIKey is an admin credential for fallbck-ctl and scripts. The raw key is never stored.
type Agent ¶
type Agent struct {
ID uuid.UUID `json:"id" db:"id"`
Hostname string `json:"hostname" db:"hostname"`
IPAddress string `json:"ip_address" db:"ip_address"`
OS string `json:"os" db:"os"`
Arch string `json:"arch" db:"arch"`
Version string `json:"version" db:"version"`
AgentType string `json:"agent_type" db:"agent_type"`
TaskQueue string `json:"task_queue" db:"task_queue"`
// DebugLogging raises the agent's log level to debug (applied via heartbeats)
DebugLogging bool `json:"debug_logging" db:"debug_logging"`
// AutoUpdate lets the agent update itself to the server's version (per-agent opt-in)
AutoUpdate bool `json:"auto_update" db:"auto_update"`
// SelfUpdate is reported by the agent when it can replace its own binary (Linux
// package or manual install; not containers, not Windows)
SelfUpdate bool `json:"self_update" db:"self_update"`
// UpdateRequestedAt is set by "Update now" in the web UI; cleared when the agent
// reports the server's version or an update error
UpdateRequestedAt *time.Time `json:"update_requested_at,omitempty" db:"update_requested_at"`
// UpdateError is the agent's last self-update failure (empty: none)
UpdateError string `json:"update_error,omitempty" db:"update_error"`
// PVEHost is reported by the agent when it runs on a Proxmox VE node
PVEHost bool `json:"pve_host" db:"pve_host"`
// DockerHost is reported by the agent when a Docker daemon answers on its host
DockerHost bool `json:"docker_host" db:"docker_host"`
// DBTools is reported by a filesystem agent that found database client tools
// (pg_dump, mysqldump/mariadb-dump, mongodump) and can therefore run database jobs
DBTools bool `json:"db_tools" db:"db_tools"`
// DBEngines are the database engines the agent reported (see CanRunDBEngine)
DBEngines []string `json:"db_engines" db:"db_engines"`
// Inventory is the compact summary the agent attaches to a heartbeat every few
// minutes (inventory.Summary); InventoryDetail the on-demand full inventory
Inventory json.RawMessage `json:"inventory,omitempty" db:"inventory"`
InventoryAt *time.Time `json:"inventory_at,omitempty" db:"inventory_at"`
InventoryDetail json.RawMessage `json:"inventory_detail,omitempty" db:"inventory_detail"`
InventoryDetailAt *time.Time `json:"inventory_detail_at,omitempty" db:"inventory_detail_at"`
Status AgentStatus `json:"status" db:"status"`
// Labels place the agent in access scopes; copied from the enrollment token
Labels Labels `json:"labels"`
LastSeenAt *time.Time `json:"last_seen_at" db:"last_seen_at"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
}
Agent represents a registered backup agent host
func (*Agent) CanRunDBEngine ¶ added in v0.11.3
CanRunDBEngine reports whether this agent can back up the engine. Filesystem agents go by the engines they report; one that only sent the older db_tools flag predates the mssql engine and is assumed to have the client tools of the other three. Kubernetes agents dump from a pod and the retired database agent predates mssql, so both handle everything except SQL Server.
type AgentAuthState ¶
AgentAuthState is the subset of agent state needed to validate an agent bearer token
type AgentCapabilities ¶ added in v0.10.1
type AgentCapabilities struct {
PVEHost bool
DockerHost bool
DBTools bool
DBEngines []string
// Version is the running binary's version (empty keeps the stored one)
Version string
// SelfUpdate / UpdateError: see Agent
SelfUpdate bool
UpdateError string
// Inventory is the summary attached to this heartbeat (nil: none this time)
Inventory json.RawMessage
}
AgentCapabilities are the host facts a filesystem agent reports with every heartbeat
type AgentStatus ¶
type AgentStatus string
AgentStatus represents the lifecycle state of an agent
const ( AgentStatusOnline AgentStatus = "online" AgentStatusOffline AgentStatus = "offline" AgentStatusBusy AgentStatus = "busy" AgentStatusError AgentStatus = "error" )
type AuditEntry ¶ added in v1.0.0
type AuditEntry struct {
ID int64 `json:"id"`
At time.Time `json:"at"`
ActorKind string `json:"actor_kind"`
Actor string `json:"actor"`
Action string `json:"action"`
ResourceKind string `json:"resource_kind"`
ResourceID string `json:"resource_id"`
ResourceName string `json:"resource_name"`
Labels Labels `json:"labels"`
SourceIP string `json:"source_ip"`
Details json.RawMessage `json:"details,omitempty"`
}
AuditEntry is one row of the append-only audit log
type AuditFilter ¶ added in v1.0.0
type AuditFilter struct {
Actor string
Action string // prefix match: "job" matches job.create, job.delete...
ResourceKind string
From, To *time.Time
Limit int
}
AuditFilter narrows ListAudit; empty fields match everything
type BackupJob ¶
type BackupJob struct {
ID uuid.UUID `json:"id" db:"id"`
Name string `json:"name" db:"name"`
AgentID uuid.UUID `json:"agent_id" db:"agent_id"`
TargetID uuid.UUID `json:"target_id" db:"target_id"`
ScheduleCron string `json:"schedule_cron" db:"schedule_cron"`
BackupPaths []string `json:"backup_paths" db:"backup_paths"`
ExcludePaths []string `json:"exclude_paths" db:"exclude_paths"`
Enabled bool `json:"enabled" db:"enabled"`
// DirectPBS makes the agent talk to PBS itself (credentials handed out per run)
// instead of through the server-side tunnel. Server-side setting only.
DirectPBS bool `json:"direct_pbs" db:"direct_pbs"`
// BackupID is the PBS backup group of filesystem, Docker, Proxmox VE and
// kubernetes jobs (database and Microsoft 365 jobs carry theirs in their config).
// Empty means the agent ID, see EffectiveBackupID.
BackupID string `json:"backup_id" db:"backup_id"`
// JobType is filesystem (BackupPaths) or database (DBConfig)
JobType string `json:"job_type" db:"job_type"`
// DBConfig is the database job specification; the password is stored but never
// returned by the API (see Sanitize)
DBConfig *dbbackup.Spec `json:"db_config,omitempty" db:"db_config"`
// K8sConfig is the kubernetes job specification
K8sConfig *k8sbackup.Spec `json:"k8s_config,omitempty" db:"k8s_config"`
// PVEConfig is the Proxmox VE host job specification
PVEConfig *pvebackup.Spec `json:"pve_config,omitempty" db:"pve_config"`
// DockerConfig is the Docker host job specification
DockerConfig *dockerbackup.Spec `json:"docker_config,omitempty" db:"docker_config"`
// M365Config is the Microsoft 365 job specification (its TenantID is also the
// m365_tenant_id column, so a tenant cannot be deleted while jobs use it)
M365Config *m365.Spec `json:"m365_config,omitempty" db:"m365_config"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
// Labels place the job and all of its runs in access scopes. On update, an
// absent field (nil) keeps the stored labels; {} clears them.
Labels Labels `json:"labels"`
// Joined fields for display
AgentName string `json:"agent_name,omitempty"`
TargetName string `json:"target_name,omitempty"`
// LastRun is the job's newest run (filled by the Jobs page; nil = never ran)
LastRun *JobLastRun `json:"last_run,omitempty" db:"-"`
}
func (*BackupJob) EffectiveBackupID ¶ added in v0.14.12
BackupJob defines what, when, and where an agent backs up EffectiveBackupID is the PBS backup group a filesystem, Docker, Proxmox VE or kubernetes job writes to: the stored backup_id, else the agent ID (with -docker / -pve for those types). Server-derived on purpose: an agent must not be able to pick another host's group by reporting its hostname.
func (*BackupJob) IsDatabase ¶ added in v0.6.0
IsDatabase reports whether the job is a database backup
func (*BackupJob) IsDocker ¶ added in v0.9.11
IsDocker reports whether the job is a Docker host backup
func (*BackupJob) IsKubernetes ¶ added in v0.7.2
IsKubernetes reports whether the job is a kubernetes backup
func (*BackupJob) IsM365 ¶ added in v0.14.0
IsM365 reports whether the job is a Microsoft 365 backup
func (*BackupJob) NextRunString ¶ added in v0.6.2
NextRunString reports when the schedule fires next, in the schedule timezone with its abbreviation; empty when the job is manual, disabled, or the expression does not parse.
type BackupRun ¶
type BackupRun struct {
ID uuid.UUID `json:"id" db:"id"`
JobID uuid.UUID `json:"job_id" db:"job_id"`
AgentID uuid.UUID `json:"agent_id" db:"agent_id"`
TargetID uuid.UUID `json:"target_id" db:"target_id"`
WorkflowID string `json:"workflow_id" db:"workflow_id"`
RunID string `json:"run_id" db:"run_id"`
Status RunStatus `json:"status" db:"status"`
StartTime *time.Time `json:"start_time" db:"start_time"`
EndTime *time.Time `json:"end_time" db:"end_time"`
BytesScanned int64 `json:"bytes_scanned" db:"bytes_scanned"`
BytesUploaded int64 `json:"bytes_uploaded" db:"bytes_uploaded"`
DedupRatio float64 `json:"dedup_ratio" db:"dedup_ratio"`
ChunkCount int `json:"chunk_count" db:"chunk_count"`
ErrorMessage string `json:"error_message" db:"error_message"`
PBSSnapshotID string `json:"pbs_snapshot_id" db:"pbs_snapshot_id"`
// LogTail is the agent's recent log output captured when the run failed
LogTail string `json:"log_tail,omitempty" db:"log_tail"`
// KeyFingerprint names the encryption key the snapshot was written with ("" = plaintext)
KeyFingerprint string `json:"key_fingerprint,omitempty" db:"key_fingerprint"`
// Details is a type-specific JSON blob (archives / databases / PVCs) for the run
// detail page; carries a top-level "type" discriminator. Empty for older runs.
Details json.RawMessage `json:"details,omitempty" db:"details"`
// Progress is the live state of a running backup (phase + per-item statuses),
// updated mid-run and polled by the detail page.
Progress json.RawMessage `json:"progress,omitempty" db:"progress"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
// Joined fields
JobName string `json:"job_name,omitempty"`
AgentName string `json:"agent_name,omitempty"`
}
BackupRun records a single execution of a backup job
func (*BackupRun) DurationString ¶ added in v0.6.0
DurationString renders how long the run took (or has been running); "-" before start
type BackupTarget ¶
type BackupTarget struct {
ID uuid.UUID `json:"id" db:"id"`
Name string `json:"name" db:"name"`
TargetType string `json:"target_type" db:"target_type"` // "pbs"
Endpoint string `json:"endpoint" db:"endpoint"`
Datastore string `json:"datastore" db:"datastore"`
Namespace string `json:"namespace" db:"namespace"`
// AuthToken is the PBS API token in clear in memory; the repository seals it with
// the server master key on write and opens it on read (column auth_token_encrypted)
AuthToken string `json:"-" db:"auth_token_encrypted"`
Fingerprint string `json:"fingerprint" db:"fingerprint"`
TLSVerify bool `json:"tls_verify" db:"tls_verify"`
PxarFormat string `json:"pxar_format" db:"pxar_format"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
// Client-side encryption: EncryptionNone or EncryptionEncrypt. The key comes from
// the target's key ring (KeyRingID); targets on one ring share the active key and
// so deduplicate against each other on PBS. EncryptionKeyID, KeyFingerprint,
// KeyCreatedAt and MasterPublicKey are the ring's active key and RSA public key,
// joined on read.
EncryptionMode string `json:"encryption_mode" db:"encryption_mode"`
KeyRingID *uuid.UUID `json:"key_ring_id,omitempty" db:"key_ring_id"`
KeyRingName string `json:"key_ring_name,omitempty" db:"-"`
EncryptionKeyID *uuid.UUID `json:"encryption_key_id,omitempty" db:"-"`
MasterPublicKey string `json:"master_public_key,omitempty" db:"-"`
KeyFingerprint string `json:"key_fingerprint,omitempty" db:"-"`
KeyCreatedAt *time.Time `json:"key_created_at,omitempty" db:"-"`
// HasToken reports whether an API token is stored (the token itself is never returned)
HasToken bool `json:"has_token" db:"-"`
Labels Labels `json:"labels"`
// TokenCheck is the last check of the API token's privileges on PBS (nil: not
// checked yet); anything but ok shows as a warning on the target
TokenCheck *pbs.TokenCheck `json:"token_check"`
}
BackupTarget represents a remote backup repository such as Proxmox Backup Server
func (*BackupTarget) Encrypted ¶ added in v0.13.0
func (t *BackupTarget) Encrypted() bool
Encrypted reports whether runs to this target encrypt client-side
func (*BackupTarget) Sanitize ¶ added in v0.6.0
func (t *BackupTarget) Sanitize() *BackupTarget
Sanitize fills derived, API-safe fields
type DB ¶
type DB struct {
Pool *pgxpool.Pool
// Sealer protects stored secrets (target API tokens, encryption keys) at rest.
// nil (tests) stores them in clear.
Sealer *secrets.Sealer
}
DB wraps the pgx connection pool and exposes repository operations
func (*DB) BindTokenAgent ¶ added in v0.11.0
BindTokenAgent records the agent that enrolled with the token
func (*DB) BindingsFor ¶ added in v1.0.0
func (d *DB) BindingsFor(ctx context.Context, email string, groups, claims []string) ([]*RoleBinding, error)
BindingsFor returns the bindings of a user (email, case-insensitive; "" matches none), of the groups it belongs to and of its claim values ("<claim>=<value>"), with their roles' permissions
func (*DB) BootstrapAdmin ¶ added in v1.0.0
BootstrapAdmin binds the built-in admin role globally to email when no binding exists yet (the first sign-in on a fresh instance). Reports whether it did.
func (*DB) BumpAgentTokenVersion ¶
BumpAgentTokenVersion invalidates every previously issued token for the agent and returns the new version that must be embedded in freshly issued tokens.
func (*DB) ClearAgentUpdateRequest ¶ added in v0.14.3
ClearAgentUpdateRequest drops a pending request (the agent reached the version)
func (*DB) CloneTarget ¶ added in v0.11.0
func (d *DB) CloneTarget(ctx context.Context, sourceID uuid.UUID, name, namespace, pxarFormat string) (*BackupTarget, error)
CloneTarget creates a new target from an existing one: same PBS endpoint, datastore, API token (the sealed column is copied as is), fingerprint, TLS setting, encryption mode, key ring and labels, and (unless overridden) pxar format, with a new name and namespace. Sharing the ring is the point of a clone: another namespace of the same datastore deduplicates against the source only with the same key.
func (*DB) CountRunsWithKey ¶ added in v0.13.0
CountRunsWithKey counts runs whose snapshot was written with the key
func (*DB) CreateBinding ¶ added in v1.0.0
func (d *DB) CreateBinding(ctx context.Context, b *RoleBinding) error
func (*DB) CreateEnrollmentToken ¶
func (d *DB) CreateEnrollmentToken(ctx context.Context, token *EnrollmentToken) error
func (*DB) CreateKeyRing ¶ added in v0.14.12
CreateKeyRing stores an empty ring (the caller activates a key next)
func (*DB) CreateRole ¶ added in v1.0.0
CreateRole stores a custom role
func (*DB) CreateTarget ¶
func (d *DB) CreateTarget(ctx context.Context, target *BackupTarget) error
func (*DB) CreateTargetKey ¶ added in v0.13.0
CreateTargetKey stores a key (sealed) on a ring
func (*DB) CreateTenant ¶ added in v0.14.0
CreateTenant stores a tenant; the secret and private key are sealed
func (*DB) DeleteBinding ¶ added in v1.0.0
DeleteBinding removes a binding, refusing (ErrLastAdmin) to remove the last one that grants rbac:manage with an empty selector, which would lock everyone out
func (*DB) DeleteEnrollmentToken ¶ added in v0.6.0
DeleteEnrollmentToken invalidates a token immediately (enrollment looks tokens up by hash, so a deleted row can never be consumed again)
func (*DB) DeleteKeyRing ¶ added in v0.14.12
DeleteKeyRing removes a ring and its keys; refused (ErrInUse) while a target uses it
func (*DB) DeleteRole ¶ added in v1.0.0
DeleteRole removes a custom role nothing is bound to (ErrInUse otherwise)
func (*DB) DeleteTenant ¶ added in v0.14.0
DeleteTenant removes a tenant that no job references (ErrTenantInUse otherwise)
func (*DB) EnsureUnlimitedEnrollmentToken ¶ added in v0.14.3
EnsureUnlimitedEnrollmentToken creates a never-expiring, unlimited-use token with the given hash unless it already exists (server --insecure-unlimited-dev-token)
func (*DB) GetAPIKeyByHash ¶
func (*DB) GetAgentAuthState ¶
GetAgentAuthState returns the token version and revocation state of an agent. Returns ErrNotFound if the agent does not exist (e.g. it was deleted).
func (*DB) GetAgentByID ¶
GetAgentByID loads an agent within scope (ErrNotFound outside it)
func (*DB) GetBinding ¶ added in v1.0.0
func (*DB) GetEnrollmentToken ¶ added in v0.11.0
func (d *DB) GetEnrollmentToken(ctx context.Context, id uuid.UUID, scope Scope) (*EnrollmentToken, error)
GetEnrollmentToken loads one token within scope (with the hostname of the agent that used it)
func (*DB) GetJobByID ¶
GetJobByID loads a job within scope (ErrNotFound outside it)
func (*DB) GetKeyRing ¶ added in v0.14.12
GetKeyRing loads a ring within scope (ErrNotFound outside it)
func (*DB) GetRunByID ¶ added in v0.3.1
GetRunByID returns a single run whose job is within scope
func (*DB) GetRunByWorkflowID ¶ added in v0.3.1
GetRunByWorkflowID returns the run record created for a Temporal workflow execution
func (*DB) GetTargetByID ¶
GetTargetByID loads a target within scope (ErrNotFound outside it)
func (*DB) GetTargetKey ¶ added in v0.13.0
GetTargetKey loads one key with its material
func (*DB) GetTenantByID ¶ added in v0.14.0
GetTenantByID returns the tenant within scope with its credentials opened
func (*DB) HasSealedSecrets ¶ added in v0.14.12
HasSealedSecrets reports whether any stored secret is already sealed, i.e. a master key existed before. A freshly generated key then means the key file was lost.
func (*DB) LatestRunByJob ¶ added in v0.11.2
LatestRunByJob returns the newest run of every job that has one
func (*DB) ListAgents ¶
ListAgents lists the agents within scope
func (*DB) ListAudit ¶ added in v1.0.0
func (d *DB) ListAudit(ctx context.Context, f AuditFilter, scope Scope) ([]*AuditEntry, error)
ListAudit returns the newest entries within scope (on the labels the object had at the time) matching the filter
func (*DB) ListBindings ¶ added in v1.0.0
func (d *DB) ListBindings(ctx context.Context) ([]*RoleBinding, error)
func (*DB) ListEnrollmentTokens ¶
ListEnrollmentTokens lists the tokens within scope
func (*DB) ListKeyRings ¶ added in v0.14.12
ListKeyRings lists the rings within scope
func (*DB) ListRingKeys ¶ added in v0.14.12
ListRingKeys lists a ring's keys (newest first) without their material
func (*DB) ListRuns ¶
ListRuns lists the newest runs whose job is within scope. Runs have no labels of their own: a run is visible exactly when its job is.
func (*DB) ListRunsByAgent ¶ added in v0.12.0
func (d *DB) ListRunsByAgent(ctx context.Context, agentID uuid.UUID, limit int, scope Scope) ([]*BackupRun, error)
ListRunsByAgent is ListRuns restricted to one agent (the agent status page)
func (*DB) ListSeenSubjects ¶ added in v1.0.0
func (d *DB) ListSeenSubjects(ctx context.Context) ([]*SeenSubject, error)
ListSeenSubjects returns what sign-ins have shown, newest first
func (*DB) ListTargets ¶
ListTargets lists the targets within scope
func (*DB) ListTenants ¶ added in v0.14.0
ListTenants returns the tenants within scope ordered by name
func (*DB) MarkRunStarted ¶ added in v0.3.1
func (d *DB) MarkRunStarted(ctx context.Context, id uuid.UUID, temporalRunID string, startedAt time.Time) error
MarkRunStarted moves a pending run to running once the workflow has prepared the session
func (*DB) MergeAgents ¶ added in v0.10.1
MergeAgents moves every job and run of the agent from onto the agent into and deletes from, in one transaction. Deleting an agent cascades to its jobs and runs, so the move must come first. It returns the number of jobs and runs moved.
func (*DB) Migrate ¶
Migrate applies all pending schema migrations to PostgreSQL. Each migration runs in its own transaction and is recorded in schema_migrations so it is applied exactly once.
func (*DB) PruneAudit ¶ added in v1.0.0
func (d *DB) PruneAudit(ctx context.Context, before time.Time, export func([]*AuditEntry) error) (int, error)
PruneAudit deletes entries older than before in batches. Each batch is handed to export first (nil: no export) and deleted only when export succeeded, in the same transaction, so a row is never gone without having reached the sink. It returns how many rows were deleted; when another server holds the prune lock it does nothing.
func (*DB) RecordSignIn ¶ added in v1.0.0
RecordSignIn remembers what a successful sign-in showed: the verified email ("" skips it), every group and every claim value
func (*DB) RequestAgentUpdate ¶ added in v0.14.3
RequestAgentUpdate asks the agent to update on its next heartbeat (the web UI's "Update now"); a previous error is cleared so the retry starts clean
func (*DB) RetireTargetKey ¶ added in v0.13.0
RetireTargetKey marks a key as no longer used for new snapshots
func (*DB) RevokeAgent ¶
RevokeAgent marks the agent as revoked; its tokens stop validating immediately
func (*DB) ScopedBindingsOfRole ¶ added in v1.0.0
ScopedBindingsOfRole counts bindings and live API keys of a role with a non-empty selector (a role that gains a global-only permission must have none)
func (*DB) SealLegacySecrets ¶ added in v0.13.0
SealLegacySecrets rewrites secrets stored in clear before the master key existed. It returns how many rows were sealed. Safe to run at every start.
func (*DB) SetAgentAutoUpdate ¶ added in v0.14.3
SetAgentAutoUpdate flips the per-agent auto-update opt-in
func (*DB) SetAgentDebugLogging ¶ added in v0.6.2
SetAgentDebugLogging flips the per-agent debug toggle (delivered on the next heartbeat)
func (*DB) SetAgentInventoryDetail ¶ added in v0.12.0
SetAgentInventoryDetail stores the on-demand full inventory
func (*DB) SetAgentLabels ¶ added in v1.0.0
SetAgentLabels replaces an agent's labels
func (*DB) SetRingActiveKey ¶ added in v0.14.12
SetRingActiveKey points the ring at a key (nil: no active key)
func (*DB) SetRunItems ¶ added in v0.9.0
func (d *DB) SetRunItems(ctx context.Context, runID uuid.UUID, updatedAt string, items map[string][]byte) error
SetRunItems merges per-item statuses into an active run's progress. Each item is written at progress.items.<key> so concurrent per-item updates never clobber.
func (*DB) SetRunPhase ¶ added in v0.9.0
SetRunPhase records the current phase of an active run (jsonb_set: no read-modify-write)
func (*DB) SetRunStatus ¶ added in v0.3.1
func (d *DB) SetRunStatus(ctx context.Context, id uuid.UUID, status RunStatus, message string, endTime *time.Time) error
SetRunStatus updates the status (and optionally end time / message) of a run
func (*DB) SetTargetEncryption ¶ added in v0.13.0
func (d *DB) SetTargetEncryption(ctx context.Context, targetID uuid.UUID, mode string, ringID *uuid.UUID) error
SetTargetEncryption switches a target's mode and key ring in one statement; mode none keeps the ring attached so re-enabling reuses it (and old snapshots keep their keys)
func (*DB) SetTargetTokenCheck ¶ added in v1.0.0
func (d *DB) SetTargetTokenCheck(ctx context.Context, id uuid.UUID, check *pbs.TokenCheck) (string, error)
SetTargetTokenCheck stores a token check result and returns the previous status ("" when the target was never checked)
func (*DB) SyncBuiltinRoles ¶ added in v1.0.0
func (d *DB) SyncBuiltinRoles(ctx context.Context, roles map[string][]string, descriptions map[string]string) error
SyncBuiltinRoles writes the built-in roles' permissions (called at every start, so a new permission reaches the built-ins without a migration)
func (*DB) TouchAPIKey ¶
TouchAPIKey records the last use of a key (best-effort, called on successful auth)
func (*DB) UpdateAgentHeartbeat ¶
func (d *DB) UpdateAgentHeartbeat(ctx context.Context, id uuid.UUID, status AgentStatus, caps AgentCapabilities) (HeartbeatState, error)
UpdateAgentHeartbeat records the heartbeat (status, capabilities, version) and returns what the response needs. An update error from the agent consumes a pending "update now" request so a failed manual update is not retried every heartbeat.
func (*DB) UpdateKeyRing ¶ added in v0.14.12
UpdateKeyRing writes a ring's name, master public key and labels
func (*DB) UpdateRole ¶ added in v1.0.0
UpdateRole replaces a custom role's description and permissions (built-ins: ErrNotFound)
func (*DB) UpdateTarget ¶ added in v0.9.0
func (d *DB) UpdateTarget(ctx context.Context, target *BackupTarget) error
UpdateTarget replaces a target's editable fields (name, endpoint, datastore, namespace, token, fingerprint, TLS, format); the encryption mode and key ring change only through SetTargetEncryption. The caller supplies the final values, including AuthToken (kept unchanged by loading the existing row first when the operator leaves the token field blank).
func (*DB) UpdateTenant ¶ added in v0.14.0
UpdateTenant replaces every editable field (the caller keeps the stored credential when the request carries none)
func (*DB) ValidateAndConsumeToken ¶
func (*DB) WriteAudit ¶ added in v1.0.0
func (d *DB) WriteAudit(ctx context.Context, e *AuditEntry) error
type EnrollmentToken ¶
type EnrollmentToken struct {
ID uuid.UUID `json:"id" db:"id"`
TokenHash string `json:"-" db:"token_hash"`
Name string `json:"name" db:"name"`
MaxUses int `json:"max_uses" db:"max_uses"`
UsesCount int `json:"uses_count" db:"uses_count"`
ExpiresAt time.Time `json:"expires_at" db:"expires_at"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
// AgentID is the agent that last enrolled with this token (onboarding waits for it)
AgentID *uuid.UUID `json:"agent_id,omitempty" db:"agent_id"`
// AgentHostname is joined for display; empty when no agent used the token
AgentHostname string `json:"agent_hostname,omitempty" db:"-"`
// Labels are copied onto every agent that enrolls with the token
Labels Labels `json:"labels"`
}
EnrollmentToken represents a one-time or multi-use token for agent onboarding
func (*EnrollmentToken) Status ¶ added in v0.6.0
func (t *EnrollmentToken) Status() string
Status describes whether the token can still be used
type HeartbeatState ¶ added in v0.14.3
type HeartbeatState struct {
DebugLogging bool
AutoUpdate bool
UpdateRequested bool
OS, Arch string
}
HeartbeatState is what the heartbeat response needs from the agent row
type JobLastRun ¶ added in v0.11.2
type JobLastRun struct {
RunID uuid.UUID `json:"run_id"`
Status RunStatus `json:"status"`
At time.Time `json:"at"`
}
JobLastRun is the newest run of a job, for list views
type KeyRing ¶ added in v0.14.12
type KeyRing struct {
ID uuid.UUID `json:"id"`
Name string `json:"name"`
ActiveKeyID *uuid.UUID `json:"active_key_id,omitempty"`
MasterPublicKey string `json:"master_public_key,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
CreatedBy string `json:"created_by,omitempty"`
// KeyFingerprint / KeyCreatedAt describe the active key, Targets names the targets
// attached to the ring (joined on read)
KeyFingerprint string `json:"key_fingerprint,omitempty"`
KeyCreatedAt *time.Time `json:"key_created_at,omitempty"`
Targets []string `json:"targets"`
Labels Labels `json:"labels"`
}
KeyRing is a set of encryption keys shared by the targets attached to it. Targets on one ring encrypt with the same active key and therefore deduplicate against each other on PBS (one datastore, many namespaces); targets on different rings never do. Rotation retires the active key for every target on the ring at once. The optional RSA master public key wraps the active key into every snapshot for recovery.
type Labels ¶ added in v1.0.0
Labels are key=value pairs on agents, targets, jobs, tenants, key rings and enrollment tokens. Access bindings select objects by them.
func (Labels) Contains ¶ added in v1.0.0
Contains reports whether every entry of sel is present in l (equality, AND)
func (Labels) Equal ¶ added in v1.0.0
Equal reports whether both hold the same entries (nil equals empty)
func (Labels) JSON ¶ added in v1.0.0
JSON is the jsonb text of the labels; pgx sends a string parameter to a jsonb column as raw JSON
type Migration ¶
Migration is a single embedded SQL migration file
func LoadMigrations ¶
LoadMigrations returns the embedded migrations ordered by version. Files are named NNN_description.sql; the numeric prefix is the version.
type Requirement ¶ added in v1.0.0
type Requirement struct {
Key string `json:"key"`
Op string `json:"op"`
Values []string `json:"values,omitempty"`
}
Requirement is one clause of a selector
func (Requirement) Matches ¶ added in v1.0.0
func (r Requirement) Matches(l Labels) bool
Matches reports whether labels satisfy the requirement
func (Requirement) String ¶ added in v1.0.0
func (r Requirement) String() string
type Role ¶ added in v1.0.0
type Role struct {
Name string `json:"name"`
Builtin bool `json:"builtin"`
Description string `json:"description"`
Permissions []string `json:"permissions"`
Bindings int `json:"bindings"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Role is a named set of permissions. Built-in roles are defined in code and rewritten at every start; they cannot be edited, only cloned.
type RoleBinding ¶ added in v1.0.0
type RoleBinding struct {
ID uuid.UUID `json:"id"`
Kind string `json:"kind"`
Subject string `json:"subject"`
Role string `json:"role"`
Selector Selector `json:"selector"`
CreatedBy string `json:"created_by"`
CreatedAt time.Time `json:"created_at"`
// Permissions of the role (joined)
Permissions []string `json:"permissions,omitempty"`
// LastSeen is the subject's last appearance at a sign-in (nil: never seen); Stale
// flags one not seen for StaleAfter
LastSeen *time.Time `json:"last_seen"`
Stale bool `json:"stale"`
}
RoleBinding grants a role to a user (verified OIDC email), a group (groups claim value) or a claim value on the objects its selector matches (empty: everything)
type RunStatus ¶
type RunStatus string
RunStatus represents the state of a backup run
const ( RunStatusPending RunStatus = "pending" RunStatusRunning RunStatus = "running" RunStatusCompleted RunStatus = "completed" RunStatusFailed RunStatus = "failed" // RunStatusCancelling: cancellation requested, waiting for the agent to stop RunStatusCancelling RunStatus = "cancelling" RunStatusCancelled RunStatus = "cancelled" )
type Scope ¶ added in v1.0.0
Scope is the set of objects one permission reaches for a principal: everything (All), nothing (zero value), or the objects matched by any of the selectors. It is the only input to both forms of the access decision: Matches for an object in hand and SQL for queries, so the two cannot drift apart.
type SeenSubject ¶ added in v1.0.0
type SeenSubject struct {
Kind string `json:"kind"`
Value string `json:"value"`
LastSeen time.Time `json:"last_seen"`
}
SeenSubject is an email, group or claim value a sign-in has shown
type Selector ¶ added in v1.0.0
type Selector []Requirement
Selector picks objects by their labels, Kubernetes style. Every requirement must hold (AND); an empty selector matches everything. Written and stored as a string:
team=web, env in (prod, stage), env!=dev, tier notin (frontend), managed, !legacy
func MustSelector ¶ added in v1.0.0
MustSelector parses a selector known to be valid (tests, constants); it panics otherwise
func ParseSelector ¶ added in v1.0.0
ParseSelector reads the string form. Keys and values follow the label syntax (ValidateLabels); at most MaxLabels requirements.
func SelectorFromLabels ¶ added in v1.0.0
SelectorFromLabels is the equality selector for a label set (key=value for each)
func (Selector) MarshalJSON ¶ added in v1.0.0
MarshalJSON writes the canonical string
func (Selector) Narrows ¶ added in v1.0.0
Narrows reports whether everything s matches is also matched by wider: every requirement of wider is implied by some requirement of s. Sufficient, not necessary: an unusual combination that would be narrower can be refused, never the other way round.
func (Selector) String ¶ added in v1.0.0
String is the canonical form: requirements sorted, values sorted and unique. Two selectors with the same meaning in the same clauses print the same, which is what the database's uniqueness and empty checks compare.
func (*Selector) UnmarshalJSON ¶ added in v1.0.0
UnmarshalJSON accepts the string form, or an object of key: value pairs (the equality-only form API clients used before set-based selectors)
type TargetKey ¶ added in v0.13.0
type TargetKey struct {
ID uuid.UUID `json:"id"`
RingID uuid.UUID `json:"ring_id"`
Key [32]byte `json:"-"`
Fingerprint string `json:"fingerprint"`
CreatedAt time.Time `json:"created_at"`
RetiredAt *time.Time `json:"retired_at,omitempty"`
CreatedBy string `json:"created_by,omitempty"`
}
TargetKey is one encryption key of a key ring. Key is in clear in memory only; the repository seals it with the server master key (column key_sealed). A retired key is kept because the snapshots written with it still need it.