bagdrop

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Oct 13, 2026 License: MPL-2.0 Imports: 19 Imported by: 0

Documentation

Overview

Package bagdrop owns the platform-plane configuration and destination resolution lifecycle for the one-way registry mirror described by ADR-0025.

Index

Constants

View Source
const CredentialKeyEnv = "DFBG_BAGDROP_CREDENTIAL_KEY"

Variables

View Source
var (
	ErrNotFound       = errors.New("bag drop configuration not found")
	ErrEnabled        = errors.New("bag drop configuration is enabled")
	ErrInvalid        = errors.New("invalid bag drop configuration")
	ErrResolution     = errors.New("bag drop destination did not resolve")
	ErrCredentialSeal = errors.New("bag drop credential sealing unavailable")
	ErrBucketNotFound = errors.New("bucket not found")
	ErrCleanupPending = errors.New("bag drop destination cleanup is pending")
)
View Source
var (
	ErrReconcilerNotRunning = errors.New("bag drop reconciler is not running in this process")
	ErrAuditUnavailable     = errors.New("bag drop sync audit is unavailable")
)

Functions

func ValidateRecord

func ValidateRecord(record *Record) error

ValidateRecord keeps the adapter enum and destination requirements in the domain layer even when a row is restored from storage.

Types

type Adapter

type Adapter interface {
	Resolve(context.Context, Destination) VerificationResult
	BeginReconcile(context.Context, Destination) (ReconcileRun, error)
}

func NewDufflebagAdapter

func NewDufflebagAdapter(endpoint, caChainPEM string) (Adapter, error)

NewDufflebagAdapter uses one dufflebag listener for both the token grant and Packer-compatible API. caChainPEM augments, rather than replaces, system trust roots.

func NewDufflebagAdapterFactory

func NewDufflebagAdapterFactory() Adapter

NewDufflebagAdapterFactory is the registry entry used by the process. It binds endpoint and trust configuration from each destination at use time.

func NewHCPPackerAdapter

func NewHCPPackerAdapter(authBase, apiBase string) Adapter

NewHCPPackerAdapter takes bases rather than reading configuration so tests exercise the exact production request shapes against httptest servers.

type AdapterError

type AdapterError struct {
	StatusCode int
	Code       int
	Summary    string
	RetryAfter time.Duration
}

func (*AdapterError) Error

func (e *AdapterError) Error() string

type AdapterKind

type AdapterKind string
const (
	AdapterHCPPacker AdapterKind = "hcp-packer"
	AdapterDufflebag AdapterKind = "dufflebag"
)

type ArtifactSnapshot

type ArtifactSnapshot struct {
	ExternalIdentifier string
	Region             string
}

type Association

type Association struct {
	OrganizationID   string
	ProjectID        string
	BucketName       string
	State            AssociationState
	FirstAttemptedAt *time.Time
	LastAttemptAt    *time.Time
	LastSyncedAt     *time.Time
	LastSyncError    *string
	CreatedAt        time.Time
	UpdatedAt        time.Time
}

func (Association) SyncStatus

func (a Association) SyncStatus() SyncStatus

type AssociationState

type AssociationState string
const (
	AssociationActive         AssociationState = "active"
	AssociationPendingRemoval AssociationState = "pending_removal"
)

type BucketSnapshot

type BucketSnapshot struct {
	Name        string
	Description string
	Versions    []VersionSnapshot
	Channels    []ChannelSnapshot
}

type BuildSnapshot

type BuildSnapshot struct {
	ID                       string
	ComponentType            string
	PackerRunUUID            string
	Platform                 string
	Labels                   map[string]string
	SourceExternalIdentifier string
	Metadata                 json.RawMessage
	Artifacts                []ArtifactSnapshot
	Sboms                    []SbomSnapshot
}

type ChannelSnapshot

type ChannelSnapshot struct {
	Name                       string
	Restricted                 bool
	AssignedVersionFingerprint *string
}

type Config

type Config struct {
	Adapter          AdapterKind
	HCPPacker        HCPPackerConfig
	Dufflebag        DufflebagConfig
	SecretSet        bool
	Enabled          bool
	LastVerification *LastVerification
	CreatedAt        time.Time
	UpdatedAt        time.Time
}

type CredentialSealer

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

func NewCredentialSealer

func NewCredentialSealer(ring *keyring.Keyring, environmentKey string) *CredentialSealer

func (*CredentialSealer) Mode

func (s *CredentialSealer) Mode() string

Mode reports which deployment key protects Bag Drop credentials.

func (*CredentialSealer) Seal

func (s *CredentialSealer) Seal(organizationID, projectID, secret string) ([]byte, error)

func (*CredentialSealer) Unseal

func (s *CredentialSealer) Unseal(organizationID, projectID string, sealed []byte) (string, error)

type Destination

type Destination struct {
	HCPPackerConfig
	Dufflebag    DufflebagConfig
	ClientSecret string
}

type DufflebagConfig

type DufflebagConfig struct {
	Endpoint       string `json:"endpoint"`
	CAChain        string `json:"ca_chain,omitempty"`
	OrganizationID string `json:"organization_id"`
	ProjectID      string `json:"project_id"`
	ClientID       string `json:"client_id"`
}

type HCPPackerConfig

type HCPPackerConfig struct {
	OrganizationID string `json:"organization_id"`
	ProjectID      string `json:"project_id"`
	ClientID       string `json:"client_id"`
}

type LastVerification

type LastVerification struct {
	VerificationResult
	VerifiedAt time.Time
}

type Project

type Project struct {
	OrganizationID string
	ProjectID      string
}

type ReconcileRepository

type ReconcileRepository interface {
	ListBagDropProjects(context.Context) ([]Project, error)
	GetBagDropConfig(context.Context, string, string) (*Record, error)
	ListBagDropAssociations(context.Context, string, string) ([]Association, error)
	GetBagDropBucketSnapshot(context.Context, string, string, string) (*BucketSnapshot, error)
	MarkBagDropAssociationAttempt(context.Context, string, string, string, time.Time) error
	RecordBagDropAssociationSuccess(context.Context, string, string, string, time.Time) error
	RecordBagDropAssociationFailure(context.Context, string, string, string, string, time.Time) error
	DeleteBagDropAssociation(context.Context, string, string, string) error
}

type Reconciler

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

func NewReconciler

func NewReconciler(
	repository ReconcileRepository, sealer *CredentialSealer, adapters Registry,
	writer audit.Writer, interval time.Duration, logger *slog.Logger,
) (*Reconciler, error)

func (*Reconciler) ReconcileAll

func (r *Reconciler) ReconcileAll(ctx context.Context) error

func (*Reconciler) ReconcileProject

func (r *Reconciler) ReconcileProject(ctx context.Context, project Project) error

func (*Reconciler) ReconcileStatus

func (r *Reconciler) ReconcileStatus(organizationID, projectID string) ReconcilerStatus

func (*Reconciler) Run

func (r *Reconciler) Run(ctx context.Context)

func (*Reconciler) Started

func (r *Reconciler) Started() <-chan struct{}

Started is closed once Run is accepting on-demand triggers.

func (*Reconciler) Trigger

func (r *Reconciler) Trigger(_ context.Context, organizationID, projectID string) error

type ReconcilerStatus

type ReconcilerStatus struct {
	Reconciling     bool
	NextPass        *time.Time
	LastPass        *time.Time
	Interval        time.Duration
	BackoffFailures int
}

type Record

type Record struct {
	OrganizationID   string
	ProjectID        string
	Adapter          AdapterKind
	HCPPacker        HCPPackerConfig
	Dufflebag        DufflebagConfig
	SealedSecret     []byte
	Enabled          bool
	LastVerification *LastVerification
	CreatedAt        time.Time
	UpdatedAt        time.Time
}

Record is the repository shape. SealedSecret is deliberately absent from Config, the only shape platform responses render.

type Registry

type Registry map[AdapterKind]Adapter

type RemoteBucket

type RemoteBucket struct {
	Description string `json:"description"`
	Versions    []RemoteVersion
}

type RemoteBuild

type RemoteBuild struct {
	ID            string `json:"id"`
	ComponentType string `json:"component_type"`
	Status        string `json:"status"`
}

type RemoteChannel

type RemoteChannel struct {
	Name                       string
	Managed                    bool
	Restricted                 bool
	AssignedVersionFingerprint *string
}

type RemoteSbom

type RemoteSbom struct {
	Name   string `json:"name"`
	Format string `json:"format"`
}

type RemoteVersion

type RemoteVersion struct {
	Fingerprint       string     `json:"fingerprint"`
	RevokeAt          *time.Time `json:"revoke_at,omitempty"`
	RevocationMessage string     `json:"revocation_message,omitempty"`
}

type RemovalOutcome

type RemovalOutcome string
const (
	RemovedClean   RemovalOutcome = "removed_clean"
	RemovalPending RemovalOutcome = "removal_pending"
)

type Repository

type Repository interface {
	GetBagDropConfig(context.Context, string, string) (*Record, error)
	PutBagDropConfig(context.Context, *Record) (*Record, error)
	DeleteBagDropConfig(context.Context, string, string) error
	RecordBagDropVerification(context.Context, string, string, VerificationResult, time.Time) (*Record, error)
	SetBagDropEnabled(context.Context, string, string, bool, *VerificationResult, time.Time) (*Record, error)
	ListBagDropAssociations(context.Context, string, string) ([]Association, error)
	PutBagDropAssociation(context.Context, Association) (*Association, error)
	RemoveBagDropAssociation(context.Context, string, string, string, time.Time) (RemovalOutcome, error)
	BagDropBucketExists(context.Context, string, string, string) (bool, error)
	HasBlockingBagDropAssociations(context.Context, string, string) (bool, error)
}

type Runtime

type Runtime struct {
	*Service
	*Reconciler
}

Runtime composes the request-facing configuration service with the process-owned reconciliation loop for platform handler injection.

type SbomSnapshot

type SbomSnapshot struct {
	Name     string
	Format   string
	Document []byte
}

type Service

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

func NewService

func NewService(repository Repository, sealer *CredentialSealer, adapters Registry) *Service

func (*Service) Associate

func (s *Service) Associate(
	ctx context.Context, organizationID, projectID, bucketName string,
) (*Association, error)

func (*Service) CredentialProtection

func (s *Service) CredentialProtection() string

CredentialProtection reports the sealer posture exposed with configuration responses.

func (*Service) Delete

func (s *Service) Delete(ctx context.Context, organizationID, projectID string) error

func (*Service) Disable

func (s *Service) Disable(ctx context.Context, organizationID, projectID string) (*Config, error)

func (*Service) Enable

func (s *Service) Enable(
	ctx context.Context, organizationID, projectID string, write *Write,
) (*Config, *VerificationResult, error)

func (*Service) Get

func (s *Service) Get(ctx context.Context, organizationID, projectID string) (*Config, error)

func (*Service) ListAssociations

func (s *Service) ListAssociations(
	ctx context.Context, organizationID, projectID string,
) ([]Association, error)

func (*Service) Status

func (s *Service) Status(
	ctx context.Context, organizationID, projectID string,
) (*Status, error)

func (*Service) Unassociate

func (s *Service) Unassociate(
	ctx context.Context, organizationID, projectID, bucketName string,
) (RemovalOutcome, error)

func (*Service) Verify

func (s *Service) Verify(
	ctx context.Context, organizationID, projectID string,
) (VerificationResult, error)

type Status

type Status struct {
	Configured   bool
	Config       *Config
	Associations []Association
}

type SyncStatus

type SyncStatus string
const (
	SyncPending  SyncStatus = "pending"
	SyncSynced   SyncStatus = "synced"
	SyncError    SyncStatus = "error"
	SyncRemoving SyncStatus = "removing"
)

type VerificationOutcome

type VerificationOutcome string
const (
	OutcomeResolved VerificationOutcome = "resolved"
	OutcomeFailed   VerificationOutcome = "failed"
)

type VerificationReason

type VerificationReason string
const (
	ReasonCredentialRefused VerificationReason = "credential_refused"
	ReasonProjectNotFound   VerificationReason = "project_not_found"
	ReasonUnreachable       VerificationReason = "unreachable"
	ReasonTLSFailure        VerificationReason = "tls_failure"
)

type VerificationResult

type VerificationResult struct {
	Outcome VerificationOutcome `json:"outcome"`
	Reason  VerificationReason  `json:"reason,omitempty"`
	Message string              `json:"message,omitempty"`
}

type VersionSnapshot

type VersionSnapshot struct {
	Fingerprint       string
	TemplateType      string
	RevokeAt          *time.Time
	RevocationMessage string
	Builds            []BuildSnapshot
}

type Write

type Write struct {
	Adapter      AdapterKind
	HCPPacker    *HCPPackerConfig
	Dufflebag    *DufflebagConfig
	ClientSecret *string
}

Jump to

Keyboard shortcuts

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