s3gateway

package
v0.2.2 Latest Latest
Warning

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

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

Documentation

Overview

Package s3gateway is the funcd S3-protocol frontend over the blob.Bucket substrate (ADR-0080), with in-platform identity via funcd-managed per-function SigV4 keypairs resolved by an in-process versitygw auth.IAMService (ADR-0085).

AuthN: every in-platform function gets a DETERMINISTIC keypair derived from a node-local master secret over its (namespace, function) Ref — funcd injects it into the sandbox env; the function never chooses its secret and cannot derive a peer's. AuthZ: every backend op is a PEP on the cedar PDP (s3::read / s3::write), exactly the spec.blob binding-as-grant model of slice 2.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DecodeIdentityAccess

func DecodeIdentityAccess(access string) (ns, name string, ok bool)

DecodeIdentityAccess maps an Identity access key back to its (namespace, name). ok=false for a non-Identity or malformed key. Used by the store-backed ExternalKeys to resolve the Identity + secret.

func IdentityAccessKey

func IdentityAccessKey(ns, name string) string

IdentityAccessKey returns the stable SigV4 access key id for a user-assigned Identity (ADR-0135): "FUNCID" + base32-noPad-upper(ns + "\x00" + name). Deterministic in (ns, name); the SECRET is NOT derived (it is generated + stored in the Identity's owned Secret, so it is rotatable). Because the prefix is not "FUNCD", the Function decodeAccess skips it and the gateway resolves it via ExternalKeys.

func LoadOrCreateMaster

func LoadOrCreateMaster(masterSecretFile, dataDir string) ([]byte, error)

LoadOrCreateMaster loads the node S3 master secret from file (ADR-0085), or, when the path is empty, from / generates+persists 0600 at <dataDir>/s3gateway/master.key. The secret is NEVER logged. A supplied masterSecretFile that does not exist is an error.

Types

type Deps

type Deps struct {
	// BucketFor resolves (namespace, Bucket name) → the substrate bucket view. ok=false
	// when no such Bucket exists for that namespace (⇒ NoSuchBucket).
	BucketFor func(ns v1.NamespaceName, bucket string) (blob.Bucket, bool)
	// Buckets lists a namespace's Bucket resources; HeadBucket and ListBuckets answer
	// from it, keeping only the Buckets the caller is bound to.
	Buckets func(ctx context.Context, ns v1.NamespaceName) ([]v1.Bucket, error)
	// PDP is the cedar authorizer; every backend op is a PEP on it (s3::read/s3::write).
	PDP authz.Authorizer
	// Master is the node master secret keypairs are derived from (ADR-0085). Required.
	Master []byte
	// External is the optional external-keypair store (the untrusted SigV4 edge); nil ⇒
	// in-platform only.
	External ExternalKeys
	// Listen is the node-private bind address (e.g. 127.0.0.1:9000).
	Listen string
	// MaxUploadBytes caps a single buffered (multipart/put) object; 0 ⇒ defaultMaxUpload.
	MaxUploadBytes int64
	// Logger is the server logger; nil ⇒ slog.Default(). The master secret is NEVER logged.
	Logger *slog.Logger
}

Deps configures the s3gateway server (ADR-0080 + ADR-0085).

type ExternalKeys

type ExternalKeys interface {
	Lookup(access string) (secret string, namespace string, ok bool)
}

ExternalKeys is the funcd store of issued external scoped keypairs — the one untrusted edge (ADR-0085). It resolves an access key to its secret + scoped namespace for the S3Identity principal. Lifecycle UX (issue/rotate/revoke) is a follow-on; this read-only seam is all the gateway needs.

type Keypair

type Keypair struct{ AccessKey, SecretKey string }

Keypair is a function's deterministic S3 credentials (ADR-0085). Pure value; no I/O.

func DeriveKeypair

func DeriveKeypair(master []byte, ns, fn string) Keypair

DeriveKeypair returns the stable per-(namespace, function) keypair (ADR-0085):

  • AccessKey = "FUNCD" + base32-noPad-upper(ns + "\x00" + fn) — decodable to the Ref via decodeAccess; not secret (knowing it grants nothing).
  • SecretKey = base64( HMAC-SHA256(master, "s3:"+ns+"/"+fn) ) — only the holder of master can compute it, so a function cannot forge a peer's secret.

Pure and deterministic: the same (master, ns, fn) always yields the same keypair, across daemon restarts (deterministic-across-restart). No storage, no rotation.

type Server

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

Server is the funcd S3 gateway: a versitygw s3api.New server over the funcd backend + in-process IAM, bound to a node-private TCP listener (ADR-0085). It is built via s3api.New (NOT embedgw.RunVersityGW) so the custom IAM is injectable.

func New

func New(d Deps) (*Server, error)

New builds the gateway server (ADR-0085). It validates Deps, constructs the in-process IAM + backend, and wires them through s3api.New with a random per-process root account (used by nothing external) so versitygw's required-root invariant is satisfied without granting anyone root. It does NOT bind a listener until Run is called.

func (*Server) Addr

func (s *Server) Addr() string

Addr returns the configured node-private listen address (host:port).

func (*Server) Close

func (s *Server) Close() error

Close gracefully shuts the server down (idempotent).

func (*Server) Ready

func (s *Server) Ready() <-chan struct{}

Ready returns a channel closed once the listener is bound and accepting (ADR-0085): callers (and tests) wait on it instead of a fixed sleep.

func (*Server) Run

func (s *Server) Run(ctx context.Context) error

Run binds the node-private listener and serves until ctx is done (ADR-0085). It is opt-in: the daemon only calls it when s3gateway.enabled. Run blocks; callers run it in a goroutine. On ctx cancellation it triggers a graceful ShutDown.

Jump to

Keyboard shortcuts

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