Help us shape the future of Go! Take the 2026 Go Developer Survey

ocitoken

package
v0.2.50 Latest Latest
Warning

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

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

Documentation

Overview

Package ocitoken mints the bearer tokens an OCI registry (CNCF Distribution, "token" auth) accepts: a short-lived JWT whose `access` claim names exact repositories and the actions allowed on each. The registry verifies a token by itself, against a certificate it was started with — it never calls back.

The chassis admin plane is the token service: a signed admin request already says who is asking and for which tenant, so the handler (chassis/server/admin/registry_token.go) decides WHAT may be granted and this package only parses the request's scopes and signs the answer.

Tokens are ES256 with the signer's certificate in the `x5c` header. A registry accepts an x5c leaf that is byte-identical to an entry of its rootcertbundle, so one self-signed certificate is the whole trust relationship, and the same token verifies on Distribution 2.8 and 3.x (which stopped matching the older `kid` form).

Index

Constants

View Source
const (
	DefaultTTL = 300 * time.Second
	MinTTL     = 60 * time.Second
	MaxTTL     = 900 * time.Second
)

TTL bounds. A token is a bearer credential for a push: long enough for a large upload to start, short enough that a leaked one is worth little.

View Source
const MaxRepositoryLen = 255

MaxRepositoryLen is the longest repository name a registry takes.

Variables

This section is empty.

Functions

func LoadPEM

func LoadPEM(raw []byte, b64 string) ([]byte, error)

LoadPEM returns the PEM for a caller holding either a file's bytes or its base64 (a secret store that keeps values, not files). The base64, when given, wins.

func Namespace

func Namespace(repository string) (namespace, rest string)

Namespace splits a repository name at its FIRST slash: the namespace, and the package's name within it (which may itself be a path).

func ValidateRepository

func ValidateRepository(name string) error

ValidateRepository checks a repository name against the OCI grammar and requires a namespace: at least `<namespace>/<name>`.

Types

type Access

type Access struct {
	Type    string   `json:"type"`
	Name    string   `json:"name"`
	Actions []string `json:"actions"`
}

Access is one entry of a token's `access` claim: a resource and what may be done to it.

func ParseScope

func ParseScope(scope string) (Access, error)

ParseScope reads one scope as a registry challenge states it, `<type>:<name>:<action>[,<action>…]` (`repository:acme/tool:pull,push`). The type is what precedes the first colon and the actions what follows the last, so a name may itself hold one. Actions come back sorted and de-duplicated. It checks the shape only: which types, names and actions may be granted is the caller's decision.

type Config

type Config struct {
	// KeyPEM is an ECDSA P-256 private key, PKCS#8 ("PRIVATE KEY") or SEC1
	// ("EC PRIVATE KEY"). An "EC PARAMETERS" block, as `openssl ecparam
	// -genkey` writes, is skipped.
	KeyPEM []byte
	// CertPEM is the key's certificate: exactly one CERTIFICATE block, the
	// same bytes the registry holds as its rootcertbundle.
	CertPEM []byte
	// Issuer is the `iss` claim (the registry's auth.token.issuer).
	Issuer string
	// Service is the `aud` claim (the registry's auth.token.service).
	Service string
	// TTL is a token's lifetime; zero is DefaultTTL, and it is clamped to
	// [MinTTL, MaxTTL].
	TTL time.Duration
}

Config is what a Signer is loaded from.

type Signer

type Signer struct {

	// Fingerprint is the hex SHA-256 of the certificate's DER: what an
	// operator compares against the registry's bundle.
	Fingerprint string
	// NotAfter is when the certificate, and so every token, stops verifying.
	NotAfter time.Time
	// contains filtered or unexported fields
}

Signer mints tokens. Safe for concurrent use.

func Load

func Load(cfg Config, now time.Time) (*Signer, error)

Load builds a Signer, refusing anything a registry would later refuse a token for: a key that is not P-256, a certificate that is not this key's, or one outside its validity at `now`.

func (*Signer) Issuer

func (s *Signer) Issuer() string

Issuer is the `iss` claim.

func (*Signer) Mint

func (s *Signer) Mint(sub, tenantID string, access []Access, now time.Time) (Token, error)

Mint signs a token granting `access` to `sub`. tenantID is carried for the registry's log and a later audit; the registry does not read it.

func (*Signer) Service

func (s *Signer) Service() string

Service is the registry this signer mints for (the `aud` claim).

func (*Signer) TTL

func (s *Signer) TTL() time.Duration

TTL is the lifetime of a minted token.

type Token

type Token struct {
	Raw      string
	ID       string // the jti claim
	IssuedAt time.Time
	Expires  time.Time
}

Token is a minted token and what a client is told about it.

Jump to

Keyboard shortcuts

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