audit

package
v1.0.0-beta1 Latest Latest
Warning

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

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

Documentation

Index

Constants

View Source
const (
	EventNameAuthenticationFlowEvaluated               = "authentication.flow.evaluated"
	EventNameAuthenticationFlowEvaluationsSuppressed   = "authentication.flow.evaluations-suppressed"
	EventNameAuthenticationCompleted                   = "authentication.completed"
	EventNameSessionPtyDecided                         = "session.pty.decided"
	EventNameSessionAgentForwardingDecided             = "session.agent-forwarding.decided"
	EventNameSessionRecordingStarted                   = "session.recording.started"
	EventNameSessionRecordingCompleted                 = "session.recording.completed"
	EventNameSessionRecordingIncomplete                = "session.recording.incomplete"
	EventNameSessionRecordingFailed                    = "session.recording.failed"
	EventNameSessionRecordingDeliveryFailed            = "session.recording.delivery.failed"
	EventNameSessionRecordingDeliverySucceeded         = "session.recording.delivery.succeeded"
	EventNameSessionTaskStarted                        = "session.task.started"
	EventNameSessionTaskCompleted                      = "session.task.completed"
	EventNamePortForwardingDirectDecided               = "port-forwarding.direct.decided"
	EventNamePortForwardingDirectOpenFailed            = "port-forwarding.direct.open-failed"
	EventNamePortForwardingDirectStarted               = "port-forwarding.direct.started"
	EventNamePortForwardingDirectCompleted             = "port-forwarding.direct.completed"
	EventNamePortForwardingReverseDecided              = "port-forwarding.reverse.decided"
	EventNameConnectionClosed                          = "connection.closed"
	EventNameHousekeepingSessionDisposeStarted         = "housekeeping.session.dispose.started"
	EventNameHousekeepingSessionDisposeCompleted       = "housekeeping.session.dispose.completed"
	EventNameHousekeepingSessionDeleteStarted          = "housekeeping.session.delete.started"
	EventNameHousekeepingSessionDeleteCompleted        = "housekeeping.session.delete.completed"
	EventNameHousekeepingRecordingDeleteStarted        = "housekeeping.recording.delete.started"
	EventNameHousekeepingRecordingDeleteCompleted      = "housekeeping.recording.delete.completed"
	EventNameHousekeepingOrphanedSessionCleanupSkipped = "housekeeping.orphaned-session.cleanup.skipped"
)
View Source
const (
	EventReasonRateLimit           = "rate-limit"
	EventReasonJournalReserve      = "journal-reserve"
	EventReasonSessionIncompatible = "session-incompatible"
	EventReasonOIDCAccessLost      = "oidc-access-lost"
	EventReasonAuthorizedKeyPolicy = "authorized-key-policy"
	EventReasonEnvironmentPolicy   = "environment-policy"
	EventReasonContextCanceled     = "context-canceled"
	EventReasonDeadlineExceeded    = "deadline-exceeded"
	EventReasonInvalidExitCode     = "invalid-exit-code"
	EventReasonInvalidRequest      = "invalid-request"
	EventReasonEnvironment         = "environment"
	EventReasonDestinationConnect  = "destination-connect"
	EventReasonDestinationRejected = "destination-rejected"
	EventReasonChannelAccept       = "channel-accept"
	EventReasonInvalidBind         = "invalid-bind"
	EventReasonDisconnected        = "disconnected"
	EventReasonMissingFlow         = "missing-flow"
	EventReasonRetentionElapsed    = "retention-elapsed"
	EventReasonExpired             = "expired"
	EventReasonRecordingCreate     = "recording-create"
	EventReasonRecordingCapture    = "recording-capture"
	EventReasonRecordingSeal       = "recording-seal"
	EventReasonAuditWrite          = "audit-write"
	EventReasonSessionError        = "session-error"
	EventReasonStartupRecovery     = "startup-recovery"
)
View Source
const MaxSessionSubsystemBytes = 256
View Source
const (
	SessionRecordingCastSignatureSchema = "bifroest.asciicast-signature/v1"
)

Variables

This section is empty.

Functions

func EncryptionRecipientFingerprint

func EncryptionRecipientFingerprint(publicKeys bfcrypto.PublicKeys) (string, error)

func LoadExistingIdentityPublicKey

func LoadExistingIdentityPublicKey(path string) (bfcrypto.PublicKey, error)

LoadExistingIdentityPublicKey reads an existing private key without creating one. Missing files are allowed; unreadable or invalid files are not.

func LoadSftpIdentityPublicKeys

func LoadSftpIdentityPublicKeys(identityFiles []string) ([]bfcrypto.PublicKey, error)

LoadSftpIdentityPublicKeys securely loads SFTP private identity files and returns only the public portions needed for key-dedicatedness validation. If loading fails, it returns every key it could load as well.

func ResolveEncryptionPublicKey

func ResolveEncryptionPublicKey(publicKey bfcrypto.PublicKeys, publicKeyFile bfcrypto.PublicKeysFile) (bfcrypto.PublicKeys, error)

func ValidateEncryptionRecipientDedicatedFrom

func ValidateEncryptionRecipientDedicatedFrom(publicKeys bfcrypto.PublicKeys, privateKeys []bfcrypto.PrivateKey) error

func ValidateEncryptionRecipientDedicatedFromAuditIdentities

func ValidateEncryptionRecipientDedicatedFromAuditIdentities(publicKeys bfcrypto.PublicKeys, identities []*Identity) error

func ValidateEncryptionRecipientDedicatedFromPublicKeys

func ValidateEncryptionRecipientDedicatedFromPublicKeys(publicKeys bfcrypto.PublicKeys, availablePublicKeys []bfcrypto.PublicKey) error

func VerifyJournalIntegrity

func VerifyJournalIntegrity(ctx context.Context, sources []JournalSource) error

VerifyJournalIntegrity verifies bytes read from stable file handles and then revalidates the selected journal tree. It does not lock live journals, so a writer may change a file after that file's final revalidation.

func VerifyLiveJournalIntegrity

func VerifyLiveJournalIntegrity(ctx context.Context, sources []JournalSource) error

func VerifySessionRecordingCastSignature

func VerifySessionRecordingCastSignature(value SessionRecordingCastSignature) (bfcrypto.PublicKey, error)

VerifySessionRecordingCastSignature verifies internal consistency and the signature. Trust in the returned public key must be established separately.

Types

type ArtifactDigest

type ArtifactDigest [sha256.Size]byte

ArtifactDigest identifies the exact bytes of a remote artifact.

func (ArtifactDigest) IsZero

func (this ArtifactDigest) IsZero() bool

func (ArtifactDigest) MarshalText

func (this ArtifactDigest) MarshalText() ([]byte, error)

func (ArtifactDigest) String

func (this ArtifactDigest) String() string

func (*ArtifactDigest) UnmarshalText

func (this *ArtifactDigest) UnmarshalText(text []byte) error

type AuthenticationMethod

type AuthenticationMethod string
const (
	AuthenticationMethodPublicKey           AuthenticationMethod = "public-key"
	AuthenticationMethodPassword            AuthenticationMethod = "password"
	AuthenticationMethodKeyboardInteractive AuthenticationMethod = "keyboard-interactive"
)

type AuthenticationPhase

type AuthenticationPhase string
const (
	AuthenticationPhaseCandidate AuthenticationPhase = "candidate"
	AuthenticationPhaseVerified  AuthenticationPhase = "verified"
)

type ErrorCategory

type ErrorCategory string
const (
	ErrorCategoryUnknown    ErrorCategory = "unknown"
	ErrorCategorySystem     ErrorCategory = "system"
	ErrorCategoryConfig     ErrorCategory = "config"
	ErrorCategoryNetwork    ErrorCategory = "network"
	ErrorCategoryUser       ErrorCategory = "user"
	ErrorCategoryPermission ErrorCategory = "permission"
	ErrorCategoryExpired    ErrorCategory = "expired"
)

type Event

type Event struct {
	Name                 EventName                        `json:"name"`
	Domain               EventDomain                      `json:"domain,omitempty"`
	Outcome              EventOutcome                     `json:"outcome,omitempty"`
	Flow                 string                           `json:"flow,omitempty"`
	ConnectionId         string                           `json:"connectionId,omitempty"`
	SessionId            string                           `json:"sessionId,omitempty"`
	OperationId          string                           `json:"operationId,omitempty"`
	RecordingId          string                           `json:"recordingId,omitempty"`
	RecordingDigest      string                           `json:"recordingDigest,omitempty"`
	Target               configuration.AuditlogTargetName `json:"target,omitempty"`
	AuthenticationMethod AuthenticationMethod             `json:"authenticationMethod,omitempty"`
	AuthenticationPhase  AuthenticationPhase              `json:"authenticationPhase,omitempty"`
	AuthorizationKind    string                           `json:"authorizationKind,omitempty"`
	SessionTask          SessionTask                      `json:"sessionTask,omitempty"`
	SessionSubsystem     string                           `json:"sessionSubsystem,omitempty"`
	Reason               EventReason                      `json:"reason,omitempty"`
	ErrorCategory        ErrorCategory                    `json:"errorCategory,omitempty"`
	ExitCode             *int                             `json:"exitCode,omitempty"`
	BytesRead            *int64                           `json:"bytesRead,omitempty"`
	BytesWritten         *int64                           `json:"bytesWritten,omitempty"`
	DurationMillis       *int64                           `json:"durationMillis,omitempty"`
	Count                *uint64                          `json:"count,omitempty"`
	Pty                  *bool                            `json:"pty,omitempty"`
	AgentForwarding      *bool                            `json:"agentForwarding,omitempty"`
	ForcedCommand        *bool                            `json:"forcedCommand,omitempty"`
}

Event is the domain payload accepted by a Recorder. The recorder adds common metadata and the journal adds its persistence envelope.

type EventDomain

type EventDomain string
const (
	EventDomainAuthentication EventDomain = "authentication"
	EventDomainConnection     EventDomain = "connection"
	EventDomainHousekeeping   EventDomain = "housekeeping"
	EventDomainPortForwarding EventDomain = "port-forwarding"
	EventDomainSession        EventDomain = "session"
)

type EventName

type EventName = string

type EventOutcome

type EventOutcome string
const (
	EventOutcomeSuccess  EventOutcome = "success"
	EventOutcomeDenied   EventOutcome = "denied"
	EventOutcomeFailure  EventOutcome = "failure"
	EventOutcomeCanceled EventOutcome = "canceled"
)

type EventReason

type EventReason = string

type Identity

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

func EnsureIdentity

func EnsureIdentity(conf *configuration.Auditlog) (*Identity, error)

EnsureIdentity loads or creates the configured audit identity. A missing key is only generated if neither journal nor Recording state could belong to it.

func EnsureIdentityWithAuditlogs

func EnsureIdentityWithAuditlogs(conf *configuration.Auditlog, auditlogs configuration.Auditlogs) (*Identity, error)

EnsureIdentityWithAuditlogs allows a recording-only identity to share an enabled auditlog's journal path if all journal state belongs to that other log's existing identity. Unknown or unowned state still blocks key creation.

func NewIdentity

func NewIdentity(privateKey bfcrypto.PrivateKey) (*Identity, error)

func (*Identity) Fingerprint

func (this *Identity) Fingerprint() string

func (*Identity) NewSessionRecordingCastSignature

func (this *Identity) NewSessionRecordingCastSignature(recordingId, digest string) (SessionRecordingCastSignature, error)

NewSessionRecordingCastSignature creates a signature for one validated cast digest without exposing a general-purpose signing operation.

func (*Identity) ProducerId

func (this *Identity) ProducerId() ProducerId

func (*Identity) PublicKey

func (this *Identity) PublicKey() bfcrypto.PublicKey

func (*Identity) SignNativeRecordingChunk

func (this *Identity) SignNativeRecordingChunk(value NativeRecordingChunkContent) ([]byte, error)

func (*Identity) SignNativeRecordingHead

func (this *Identity) SignNativeRecordingHead(value NativeRecordingHeadContent) ([]byte, error)

func (*Identity) SignNativeRecordingHeader

func (this *Identity) SignNativeRecordingHeader(value NativeRecordingHeaderContent) ([]byte, error)

func (*Identity) SignNativeRecordingSeal

func (this *Identity) SignNativeRecordingSeal(value NativeRecordingSealContent) ([]byte, error)

func (*Identity) ValidateDedicatedFrom

func (this *Identity) ValidateDedicatedFrom(privateKeys []bfcrypto.PrivateKey) error

ValidateDedicatedFrom rejects identities that reuse an SSH private key.

func (*Identity) ValidateDedicatedFromPublicKeys

func (this *Identity) ValidateDedicatedFromPublicKeys(publicKeys []bfcrypto.PublicKey) error

ValidateDedicatedFromPublicKeys rejects identities reused by SFTP targets.

type JournalSource

type JournalSource struct {
	Name                        string
	Directory                   string
	ExpectedProducerId          ProducerId
	ExpectedEncryptionRecipient string
	DecryptionIdentities        []bfcrypto.PrivateKey
	WithSensitive               bool
}

type NativeRecordingChunkContent

type NativeRecordingChunkContent struct {
	Sequence         uint64                  `cbor:"1,keyasint"`
	PreviousUnitHash [32]byte                `cbor:"2,keyasint"`
	DecodedLength    uint32                  `cbor:"3,keyasint"`
	StoredPayload    []byte                  `cbor:"4,keyasint"`
	StoredHash       [32]byte                `cbor:"5,keyasint"`
	CastHashState    [32]byte                `cbor:"6,keyasint"`
	CastHashBytes    uint64                  `cbor:"7,keyasint"`
	FinalStatus      uint8                   `cbor:"9,keyasint,omitempty"`
	CastDigest       *[32]byte               `cbor:"10,keyasint,omitempty"`
	CastSignature    []byte                  `cbor:"11,keyasint,omitempty"`
	CastBytes        *uint64                 `cbor:"12,keyasint,omitempty"`
	EndedAt          *nativeformat.Timestamp `cbor:"13,keyasint,omitempty"`
	LastElapsedNanos *uint64                 `cbor:"14,keyasint,omitempty"`
}

type NativeRecordingHeadContent

type NativeRecordingHeadContent struct {
	Version       uint8    `cbor:"1,keyasint"`
	RecordingId   [16]byte `cbor:"2,keyasint"`
	ProducerId    [32]byte `cbor:"3,keyasint"`
	PrefixBytes   uint64   `cbor:"4,keyasint"`
	ChunkCount    uint64   `cbor:"5,keyasint"`
	LastUnitHash  [32]byte `cbor:"6,keyasint"`
	CastHashState [32]byte `cbor:"7,keyasint"`
	CastHashBytes uint64   `cbor:"8,keyasint"`
}

type NativeRecordingHeaderContent

type NativeRecordingHeaderContent struct {
	Version     uint8                  `cbor:"1,keyasint"`
	Encryption  uint8                  `cbor:"2,keyasint"`
	RecordingId [16]byte               `cbor:"3,keyasint"`
	ProducerId  [32]byte               `cbor:"4,keyasint"`
	PublicKey   []byte                 `cbor:"5,keyasint"`
	StartedAt   nativeformat.Timestamp `cbor:"6,keyasint"`
	Recipient   string                 `cbor:"7,keyasint,omitempty"`
}

The four content types encode exactly the unsigned CBOR wire maps. Keep these key assignments in sync with pkg/recording/native-wire.go.

type NativeRecordingSealContent

type NativeRecordingSealContent struct {
	Status        uint8                  `cbor:"1,keyasint"`
	ChunkCount    uint64                 `cbor:"2,keyasint"`
	LastUnitHash  [32]byte               `cbor:"3,keyasint"`
	ContentHash   [32]byte               `cbor:"4,keyasint"`
	CastDigest    [32]byte               `cbor:"5,keyasint"`
	CastSignature []byte                 `cbor:"6,keyasint"`
	CastBytes     uint64                 `cbor:"7,keyasint"`
	EndedAt       nativeformat.Timestamp `cbor:"8,keyasint"`
}

type ProducerId

type ProducerId [sha256.Size]byte

ProducerId identifies the audit producer independently from process and chain lifetimes. Its text form is safe to use as a path component.

func (ProducerId) IsZero

func (this ProducerId) IsZero() bool

func (ProducerId) MarshalText

func (this ProducerId) MarshalText() ([]byte, error)

func (*ProducerId) Set

func (this *ProducerId) Set(text string) error

func (ProducerId) String

func (this ProducerId) String() string

func (*ProducerId) UnmarshalText

func (this *ProducerId) UnmarshalText(text []byte) error

type RecordOrder

type RecordOrder string
const (
	RecordOrderChain         RecordOrder = "chain"
	RecordOrderChronological RecordOrder = "chronological"
)

type Recorder

type Recorder interface {
	Record(context.Context, Event) error
	io.Closer
}

Recorder persists audit events according to the configured durability and failure policy.

func NewNoopRecorder

func NewNoopRecorder() Recorder

NewNoopRecorder creates a recorder that discards every event. It is used when audit logging is disabled.

func NewRecorder

func NewRecorder(conf *configuration.Auditlog, identity *Identity) (Recorder, error)

NewRecorder creates the configured audit recorder. Disabled audit logging returns a no-op recorder without inspecting the identity or filesystem.

type RemoteArtifact

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

RemoteArtifact describes one byte-exact artifact below its producer's remote directory. Content returns a fresh view positioned at offset zero. Targets must not retain or close that view and must publish synchronously.

func NewRemoteArtifact

func NewRemoteArtifact(producerId ProducerId, fileName string, digest ArtifactDigest, size int64, content io.ReaderAt) (RemoteArtifact, error)

NewRemoteArtifact constructs an artifact without reading its content. Remote target wrappers call ValidateContext immediately before publication.

func (RemoteArtifact) Content

func (this RemoteArtifact) Content() io.ReadSeeker

func (RemoteArtifact) Digest

func (this RemoteArtifact) Digest() ArtifactDigest

func (RemoteArtifact) FileName

func (this RemoteArtifact) FileName() string

func (RemoteArtifact) ProducerId

func (this RemoteArtifact) ProducerId() ProducerId

func (RemoteArtifact) RemotePath

func (this RemoteArtifact) RemotePath() string

func (RemoteArtifact) Size

func (this RemoteArtifact) Size() int64

func (RemoteArtifact) Validate

func (this RemoteArtifact) Validate() error

func (RemoteArtifact) ValidateContext

func (this RemoteArtifact) ValidateContext(ctx context.Context) error

type RemoteArtifactDelivery

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

RemoteArtifactDelivery owns one independent, sequential artifact delivery worker per target. Receipts are authoritative and local artifacts are never removed by this coordinator.

func NewRemoteArtifactDelivery

func NewRemoteArtifactDelivery(ctx context.Context, sealedDirectory string, source RemoteArtifactSource, receipts *RemoteArtifactReceipts, targets *RemoteArtifactTargets, auditor RemoteArtifactDeliveryAuditor) (*RemoteArtifactDelivery, error)

NewRemoteArtifactDelivery prepares asynchronous delivery for a sealed source. The coordinator owns targets after a successful return, but does not own the source or receipt store.

func (*RemoteArtifactDelivery) Close

func (this *RemoteArtifactDelivery) Close() error

func (*RemoteArtifactDelivery) Flush

func (this *RemoteArtifactDelivery) Flush(ctx context.Context) error

Flush captures the sealed names visible when it starts, explicitly wakes workers (including those in failure backoff), and waits for every destination selected by those artifacts' receipts to be durably acknowledged.

func (*RemoteArtifactDelivery) Start

func (this *RemoteArtifactDelivery) Start() error

type RemoteArtifactDeliveryAuditEvent

type RemoteArtifactDeliveryAuditEvent struct {
	State         RemoteArtifactDeliveryAuditState
	Scope         RemoteTargetScope
	FileName      string
	OperationId   string
	ErrorCategory ErrorCategory
	// contains filtered or unexported fields
}

type RemoteArtifactDeliveryAuditState

type RemoteArtifactDeliveryAuditState string
const (
	RemoteArtifactDeliveryAuditFailed    RemoteArtifactDeliveryAuditState = "failed"
	RemoteArtifactDeliveryAuditSucceeded RemoteArtifactDeliveryAuditState = "succeeded"
)

type RemoteArtifactDeliveryAuditor

type RemoteArtifactDeliveryAuditor interface {
	RecordRemoteArtifactDelivery(context.Context, RemoteArtifactDeliveryAuditEvent) error
}

type RemoteArtifactHandle

type RemoteArtifactHandle interface {
	RemoteArtifact() (RemoteArtifact, error)
	io.Closer
}

RemoteArtifactHandle owns one verified, sealed artifact. Close must be idempotent and safe while an operation using the artifact is being canceled.

type RemoteArtifactLifecycleEvent

type RemoteArtifactLifecycleEvent struct {
	Auditlog       configuration.AuditlogName
	FileName       string
	ArtifactDigest ArtifactDigest
	Event          Event
}

RemoteArtifactLifecycleEvent is an immutable terminal event awaiting audit persistence. Event data is replayed byte-for-byte from signed local state.

type RemoteArtifactReceiptQuota

type RemoteArtifactReceiptQuota interface {
	Reserve(uint64) error
	Reconcile(uint64, int64, int64) error
}

type RemoteArtifactReceipts

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

RemoteArtifactReceipts owns the durable delivery receipts for one Recording repository. Prepare must complete before the sealed artifact is published.

func NewRemoteArtifactReceipts

func NewRemoteArtifactReceipts(recordingDirectory string, identity *Identity, auditlog configuration.AuditlogName, targets *RemoteArtifactTargets, quota RemoteArtifactReceiptQuota) (*RemoteArtifactReceipts, error)

func NewRemoteArtifactReceiptsWithoutAudit

func NewRemoteArtifactReceiptsWithoutAudit(recordingDirectory string, identity *Identity, auditlog configuration.AuditlogName, targets *RemoteArtifactTargets, quota RemoteArtifactReceiptQuota) (*RemoteArtifactReceipts, error)

NewRemoteArtifactReceiptsWithoutAudit creates signed receipts without any lifecycle, delivery, or retention audit obligations.

func (*RemoteArtifactReceipts) Acknowledge

func (this *RemoteArtifactReceipts) Acknowledge(ctx context.Context, artifact RemoteArtifact, target configuration.AuditlogTargetName, acknowledgedAt time.Time) error

func (*RemoteArtifactReceipts) BeginLifecycle

func (this *RemoteArtifactReceipts) BeginLifecycle(ctx context.Context, fileName string, startedAt time.Time, event Event) error

func (*RemoteArtifactReceipts) CleanupOrphanedLifecycles

func (this *RemoteArtifactReceipts) CleanupOrphanedLifecycles(ctx context.Context) error

CleanupOrphanedLifecycles removes pre-create intents after recording startup recovery has consumed every recoverable active artifact.

func (*RemoteArtifactReceipts) Close

func (this *RemoteArtifactReceipts) Close() error

func (*RemoteArtifactReceipts) CompleteLifecycle

func (this *RemoteArtifactReceipts) CompleteLifecycle(ctx context.Context, pending RemoteArtifactLifecycleEvent) error

func (*RemoteArtifactReceipts) DiscardLifecycle

func (this *RemoteArtifactReceipts) DiscardLifecycle(ctx context.Context, fileName string) error

DiscardLifecycle removes an intent only when no receipt exists. Callers must first establish that no active, staged, or sealed artifact survives.

func (*RemoteArtifactReceipts) LifecyclePrepared

func (this *RemoteArtifactReceipts) LifecyclePrepared(ctx context.Context, fileName string) (bool, error)

LifecyclePrepared reports whether artifact preparation has durably bound the terminal event. Pending events remain prepared until they are completed.

func (*RemoteArtifactReceipts) ListRetentionCandidates

func (this *RemoteArtifactReceipts) ListRetentionCandidates(ctx context.Context, cutoff time.Time) ([]RemoteArtifactRetentionCandidate, error)

ListRetentionCandidates returns fully acknowledged artifacts whose retention start is at or before the supplied cutoff.

func (*RemoteArtifactReceipts) ListSigned

ListSigned returns validated receipt names for comparison with published artifacts.

func (*RemoteArtifactReceipts) MarkRetentionCompleted

MarkRetentionCompleted durably marks the completion audit as pending before the retention receipt can be removed.

func (*RemoteArtifactReceipts) MarkRetentionDeleting

func (this *RemoteArtifactReceipts) MarkRetentionDeleting(ctx context.Context, candidate RemoteArtifactRetentionCandidate, cutoff time.Time) error

MarkRetentionDeleting durably records that the matching artifact was verified and retention deletion has started.

func (*RemoteArtifactReceipts) PendingLifecycle

func (this *RemoteArtifactReceipts) PendingLifecycle(ctx context.Context) ([]RemoteArtifactLifecycleEvent, error)

func (*RemoteArtifactReceipts) Prepare

func (this *RemoteArtifactReceipts) Prepare(ctx context.Context, artifact RemoteArtifact, sealedAt time.Time) error

func (*RemoteArtifactReceipts) PrepareLifecycle

func (this *RemoteArtifactReceipts) PrepareLifecycle(ctx context.Context, artifact RemoteArtifact, sealedAt time.Time, recordingDigest string, interrupted bool) error

PrepareLifecycle persists the receipt and binds a pending terminal event to both the outer artifact and the canonical Cast content digest.

func (*RemoteArtifactReceipts) PromoteLifecycle

func (this *RemoteArtifactReceipts) PromoteLifecycle(ctx context.Context, artifact RemoteArtifact) error

PromoteLifecycle makes a prepared terminal event replayable after the local repository has atomically published and verified the exact artifact.

func (*RemoteArtifactReceipts) Recover

func (this *RemoteArtifactReceipts) Recover(ctx context.Context) error

Recover validates and completes interrupted receipt replacements before the recording repository performs operations that may need spool capacity.

func (*RemoteArtifactReceipts) RemoveRetentionCandidate

func (this *RemoteArtifactReceipts) RemoveRetentionCandidate(ctx context.Context, candidate RemoteArtifactRetentionCandidate, cutoff time.Time) error

RemoveRetentionCandidate removes the durable receipt after its artifact has already been removed and its completion audit has succeeded. The signed receipt is revalidated under the store lock.

func (*RemoteArtifactReceipts) Require

func (this *RemoteArtifactReceipts) Require(ctx context.Context, artifact RemoteArtifact) error

func (*RemoteArtifactReceipts) StageLifecycle

func (this *RemoteArtifactReceipts) StageLifecycle(ctx context.Context, fileName string, event Event) error

func (*RemoteArtifactReceipts) ValidateDeliveryTargets

func (this *RemoteArtifactReceipts) ValidateDeliveryTargets(ctx context.Context, source RemoteArtifactSource, targets *RemoteArtifactTargets) error

ValidateDeliveryTargets rejects configuration changes that would strand a sealed artifact with an outstanding delivery or audit obligation.

type RemoteArtifactRetentionCandidate

type RemoteArtifactRetentionCandidate struct {
	FileName           string
	ArtifactDigest     ArtifactDigest
	Size               int64
	RetentionStartedAt time.Time
	DeletionStarted    bool
	CompletionPending  bool
	AuditOperationId   string
}

RemoteArtifactRetentionCandidate identifies a fully acknowledged artifact whose signed receipt permits retention cleanup.

type RemoteArtifactSignedReceipt

type RemoteArtifactSignedReceipt struct {
	FileName                 string
	RetentionDeletionStarted bool
}

RemoteArtifactSignedReceipt identifies a validated receipt and whether its durable retention deletion marker permits the artifact to be absent.

type RemoteArtifactSource

type RemoteArtifactSource interface {
	ListSealedArtifactNames(context.Context) ([]string, error)
	OpenSealedArtifact(context.Context, string) (RemoteArtifactHandle, error)
}

RemoteArtifactSource provides immutable sealed artifacts by file name. A successful OpenSealedArtifact must return a handle whose RemoteArtifact has already been verified against the local sealed representation.

type RemoteArtifactTarget

type RemoteArtifactTarget interface {
	PublishArtifact(context.Context, RemoteArtifact) error
}

RemoteArtifactTarget is an optional capability implemented in addition to RemoteTarget. PublishArtifact has the same atomicity and idempotency contract as RemoteTarget.Publish and must verify content against ArtifactDigest.

type RemoteArtifactTargets

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

RemoteArtifactTargets owns an artifact-capable target set in configuration order. It performs no publication and starts no background work.

func NewRemoteArtifactTargets

func NewRemoteArtifactTargets(ctx context.Context, auditlogName configuration.AuditlogName, configurations configuration.AuditlogTargets) (*RemoteArtifactTargets, error)

func (*RemoteArtifactTargets) Close

func (this *RemoteArtifactTargets) Close() error

type RemoteDelivery

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

RemoteDelivery owns one independent, sequential delivery worker per target. It never removes authoritative local journal segments.

func NewRemoteDelivery

func NewRemoteDelivery(ctx context.Context, conf *configuration.Auditlog, identity *Identity) (*RemoteDelivery, error)

NewRemoteDelivery prepares targets and their durable cursors without doing network I/O. Call Start after the surrounding service is fully prepared.

func (*RemoteDelivery) Close

func (this *RemoteDelivery) Close() error

func (*RemoteDelivery) Flush

func (this *RemoteDelivery) Flush(ctx context.Context) error

Flush wakes all workers and waits until every target has durably confirmed the sealed segments visible when Flush starts.

func (*RemoteDelivery) Start

func (this *RemoteDelivery) Start() error

type RemoteTarget

type RemoteTarget interface {
	Publish(context.Context, SealedSegment) error
	io.Closer
}

RemoteTarget publishes complete sealed segments under SealedSegment's RemotePath. Publish must honor context cancellation and be idempotent: identical existing content succeeds, conflicting content is rejected, and partial content is never exposed under the final path. Close must be idempotent and safe after the coordinator cancels an active Publish context. A custom Close must not wait for Publish unless it also unblocks that call. Retry and retention policies are owned by the coordinator.

type RemoteTargetDestinationIdentity

type RemoteTargetDestinationIdentity string

RemoteTargetDestinationIdentity is a stable, canonical description of the destination selected by a custom target configuration. It must change whenever the effective destination or tenant changes, including a rendered username when it scopes storage, but must not contain passwords, tokens, private keys, or other secret credential material.

type RemoteTargetFactory

RemoteTargetFactory constructs a custom target and its effective settings. Every invocation must return an independently owned target that can be closed without affecting targets returned by other invocations. DestinationIdentity must be non-empty and PublishAttemptTimeout positive.

func RegisterRemoteTarget

func RegisterRemoteTarget[C configuration.AuditlogTargetV](configurationFactory configuration.AuditlogTargetCodecFactory, factory RemoteTargetFactory[C]) RemoteTargetFactory[C]

RegisterRemoteTarget is the normal public registration entry point for a custom target. It binds its configuration codec and runtime implementation. Registrations are expected during package initialization.

type RemoteTargetScope

type RemoteTargetScope struct {
	Auditlog configuration.AuditlogName
	Target   configuration.AuditlogTargetName
}

func (RemoteTargetScope) Validate

func (this RemoteTargetScope) Validate() error

type RemoteTargetSettings

type RemoteTargetSettings struct {
	DestinationIdentity   RemoteTargetDestinationIdentity
	PublishAttemptTimeout time.Duration
}

RemoteTargetSettings describe the effective, non-secret delivery settings returned by a custom target factory from the same snapshot as the target.

type RemoteTargets

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

RemoteTargets owns a target set in configuration order. It starts no background work; delivery orchestration is intentionally separate.

func NewRemoteTargets

func NewRemoteTargets(ctx context.Context, auditlogName configuration.AuditlogName, configurations configuration.AuditlogTargets) (*RemoteTargets, error)

func (*RemoteTargets) Close

func (this *RemoteTargets) Close() error

type SealableRecorder

type SealableRecorder interface {
	Recorder
	Seal() error
}

SealableRecorder can publish the current non-empty local segment while retaining the journal process lock for a bounded remote-delivery flush.

type SealedSegment

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

SealedSegment describes one immutable, locally verified native audit segment. Content returns a fresh view positioned at offset zero. Targets must not retain or close that view and must publish synchronously before returning.

func (SealedSegment) Content

func (this SealedSegment) Content() io.ReadSeeker

func (SealedSegment) FileName

func (this SealedSegment) FileName() string

func (SealedSegment) Hash

func (this SealedSegment) Hash() SegmentHash

func (SealedSegment) ProducerId

func (this SealedSegment) ProducerId() ProducerId

func (SealedSegment) RemotePath

func (this SealedSegment) RemotePath() string

func (SealedSegment) Sequence

func (this SealedSegment) Sequence() uint64

func (SealedSegment) Size

func (this SealedSegment) Size() int64

func (SealedSegment) Validate

func (this SealedSegment) Validate() error

func (SealedSegment) ValidateContext

func (this SealedSegment) ValidateContext(ctx context.Context) error

type SegmentHash

type SegmentHash [sha256.Size]byte

SegmentHash is the domain-separated hash bound to a sealed segment's file name. It is not a plain SHA-256 checksum of the file contents.

func (SegmentHash) IsZero

func (this SegmentHash) IsZero() bool

func (SegmentHash) MarshalText

func (this SegmentHash) MarshalText() ([]byte, error)

func (SegmentHash) String

func (this SegmentHash) String() string

func (*SegmentHash) UnmarshalText

func (this *SegmentHash) UnmarshalText(text []byte) error

type SessionRecordingCastSignature

type SessionRecordingCastSignature struct {
	Schema      string     `json:"schema"`
	RecordingId string     `json:"recordingId"`
	ProducerId  ProducerId `json:"producerId"`
	Digest      string     `json:"digest"`
	PublicKey   []byte     `json:"publicKey"`
	Signature   []byte     `json:"signature"`
}

type SessionTask

type SessionTask string
const (
	SessionTaskShell     SessionTask = "shell"
	SessionTaskExec      SessionTask = "exec"
	SessionTaskSftp      SessionTask = "sftp"
	SessionTaskSubsystem SessionTask = "subsystem"
)

type SuppressibleRecorder

type SuppressibleRecorder interface {
	Recorder
	RecordSuppressible(context.Context, Event) (bool, error)
}

SuppressibleRecorder can decline a low-priority event without turning it into a recording failure. Regular Record calls always retain fail-closed semantics.

type Verification

type Verification struct {
	Journals []VerifiedJournal `json:"journals"`
	// contains filtered or unexported fields
}

func VerifyJournals

func VerifyJournals(ctx context.Context, sources []JournalSource) (*Verification, error)

VerifyJournals has the same point-in-time semantics as VerifyJournalIntegrity and materializes records from the handles whose contents were verified.

func VerifyLiveJournals

func VerifyLiveJournals(ctx context.Context, sources []JournalSource) (*Verification, error)

VerifyLiveJournals exports a verified prefix bounded by the signed head read for each producer. Later appends and head replacements are not part of it. A producer ID must be supplied out of band; the head alone is not a trust root.

func (*Verification) ExportJSONLines

func (this *Verification) ExportJSONLines(output io.Writer, order RecordOrder) error

func (*Verification) Records

func (this *Verification) Records() []VerifiedRecord

type VerifiedJournal

type VerifiedJournal struct {
	Name          string `json:"name"`
	Directory     string `json:"directory"`
	ProducerCount uint64 `json:"producerCount"`
	SegmentCount  uint64 `json:"segmentCount"`
	RecordCount   uint64 `json:"recordCount"`
}

type VerifiedRecord

type VerifiedRecord struct {
	Auditlog           string     `json:"auditlog"`
	ProducerId         ProducerId `json:"producerId"`
	SegmentSequence    uint64     `json:"segmentSequence"`
	SegmentRecordIndex uint64     `json:"segmentRecordIndex"`
	Id                 uuid.UUID  `json:"id"`
	RecordedAt         time.Time  `json:"recordedAt"`
	Event              Event      `json:"event"`
	PreviousHash       string     `json:"previousHash"`
	Hash               string     `json:"hash"`
}

Jump to

Keyboard shortcuts

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