ocitoken

package
v0.2.38 Latest Latest
Warning

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

Go to latest
Published: Oct 3, 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