token

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Oct 11, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package token makes and reads the tokens a client presents to a daemon's TCP listener, and manages the daemon's record of them.

A token is Prefix and a secret, usually followed by an underscore and the daemon's fingerprint:

dicer_<secret>_<fingerprint>

The daemon checks the secret, and keeps only its SHA-256. The client checks the fingerprint, the SHA-256 of the daemon's public key, so that it never sends the secret to anyone else. A token has no fingerprint when the daemon's certificate is one clients verify for themselves. A token holds no address: the client says where the daemon is.

Index

Constants

View Source
const (

	// MinSecretLength is the fewest characters a secret may have.
	MinSecretLength = 32
)
View Source
const Prefix = "dicer_"

Prefix starts every token, so that a token is recognised for what it is, by a person or by a secret scanner.

Variables

View Source
var ErrInvalid = errors.New("invalid token")

ErrInvalid is a string that is not a token, or a secret that cannot be one's.

Functions

func Fingerprint

func Fingerprint(cert *x509.Certificate) string

Fingerprint returns the fingerprint of the public key cert holds: its SHA-256, hex-encoded. A certificate renewed with the same key keeps it.

func Format

func Format(secret, fingerprint string) string

Format returns the token for a secret and the daemon's fingerprint. An empty fingerprint leaves it out.

func NewSecret

func NewSecret() string

NewSecret returns a new random secret.

func Parse

func Parse(s string) (secret, fingerprint string, err error)

Parse returns a token's secret and the fingerprint it holds, if any. It returns an error wrapping ErrInvalid if s is not a token.

func SecretSHA256

func SecretSHA256(secret string) string

SecretSHA256 returns the SHA-256 of a secret, hex-encoded: what the daemon keeps in its place.

func ValidateSecret

func ValidateSecret(s string) error

ValidateSecret returns an error wrapping ErrInvalid unless s can be a token's secret: at least MinSecretLength letters and digits.

Types

type Config

type Config struct {
	// Store keeps the tokens. It is required.
	Store Store
}

Config configures a Manager.

type Manager

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

Manager creates, rotates and deletes tokens, and finds the token a secret belongs to. It keeps only each secret's SHA-256. It is safe for concurrent use.

func NewManager

func NewManager(cfg Config) *Manager

NewManager returns a Manager.

func (*Manager) Create

func (m *Manager) Create(name, secret string, scopes []Scope) (Token, string, error)

Create records a token named name with scopes, and returns it with its secret, the only time the secret is returned. An empty secret is replaced by a new one. A secret another token has is refused with an errdefs.ErrExists error.

func (*Manager) Delete

func (m *Manager) Delete(nameOrID string) error

Delete removes a token, which no longer works.

func (*Manager) RecordUse

func (m *Manager) RecordUse(nameOrID string, at time.Time) error

RecordUse records that a token was used at at.

func (*Manager) Rotate

func (m *Manager) Rotate(nameOrID, secret string) (Token, string, error)

Rotate gives a token a new secret, and returns it with that secret. An empty secret is replaced by a new one. The old secret no longer works.

func (*Manager) Token

func (m *Manager) Token(nameOrID string) (Token, error)

Token returns a token by name or ID.

func (*Manager) TokenBySecret

func (m *Manager) TokenBySecret(secret string) (Token, error)

TokenBySecret returns the token whose secret is secret, or an errdefs.ErrNotFound error if there is none.

func (*Manager) Tokens

func (m *Manager) Tokens() []Token

Tokens returns every token, sorted by name.

type Scope

type Scope string

Scope is what a token allows: ScopeAll, or an action on a kind of resource, written RESOURCE:ACTION. A read scope allows the calls that only look at its resource. A write scope also allows those that change it.

const (
	ScopeInstancesRead  Scope = "instances:read"
	ScopeInstancesWrite Scope = "instances:write"
	ScopeSnapshotsRead  Scope = "snapshots:read"
	ScopeSnapshotsWrite Scope = "snapshots:write"
	ScopeNetworksRead   Scope = "networks:read"
	ScopeNetworksWrite  Scope = "networks:write"
	ScopeVolumesRead    Scope = "volumes:read"
	ScopeVolumesWrite   Scope = "volumes:write"
	ScopeImagesRead     Scope = "images:read"
	ScopeImagesWrite    Scope = "images:write"
	ScopeKernelsRead    Scope = "kernels:read"
	ScopeKernelsWrite   Scope = "kernels:write"
	ScopeTokensRead     Scope = "tokens:read"
	ScopeTokensWrite    Scope = "tokens:write"
	ScopeEventsRead     Scope = "events:read"
)

The scopes of each kind of resource. Events, the log of what happens to every other resource, can only be read.

const ScopeAll Scope = "*"

ScopeAll allows everything, now and as the API grows.

func (Scope) Validate

func (s Scope) Validate() error

Validate returns an invalid argument error unless s is ScopeAll or the scope of a kind of resource.

type Store

type Store interface {
	CreateToken(t Token) error
	Token(nameOrID string) (Token, error)
	TokenBySecretSHA256(secretSHA256 string) (Token, error)
	Tokens() []Token
	UpdateToken(t Token) error
	RecordTokenUse(nameOrID string, at time.Time) error
	DeleteToken(nameOrID string) error
}

Store keeps the tokens.

type Token

type Token struct {
	ID   string `yaml:"id"`
	Name string `yaml:"name"`

	// SecretSHA256 is the SHA-256 of the token's secret, hex-encoded.
	SecretSHA256 string `yaml:"secret_sha256"`

	// Scopes are what the token allows.
	Scopes []Scope `yaml:"scopes"`

	CreatedAt time.Time `yaml:"created_at"`
	UpdatedAt time.Time `yaml:"updated_at"`

	// LastUsedAt is when the token last made a call, to the minute. It is
	// zero for a token never used.
	LastUsedAt time.Time `yaml:"last_used_at,omitempty"`
}

Token is a credential a client presents to the daemon's TCP listener. The daemon keeps the SHA-256 of its secret, never the secret itself.

func (Token) Allows

func (t Token) Allows(scope Scope) bool

Allows reports whether the token's scopes allow scope: it has ScopeAll, scope itself, or, for a read scope, the write scope of the same resource.

func (Token) AllowsAll

func (t Token) AllowsAll(scopes []Scope) bool

AllowsAll reports whether the token's scopes allow every one of scopes, so that a token with them could do nothing this one cannot.

func (Token) Validate

func (t Token) Validate() error

Validate returns an invalid argument error unless the token has a valid name, a secret's SHA-256 and at least one scope, each of them valid and none repeated.

Jump to

Keyboard shortcuts

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