Documentation
¶
Overview ¶
Package config is what each process of this repository is configured with: four documents, each read from one file and validated against a JSON Schema before anything starts.
- three service documents, one per process: `serve`, `controller-github` and `controller-slack`, saying how the process runs: listeners, storage, signing, lifetimes;
- one policy document, `policy`, saying what the installation decides: the access model's tables, whom the token exchange trusts, which Apps an operator may make, what each controller may change, and what is copied out. Every service document names it (`policy.file`).
Each document carries `apiVersion`. This build writes v2 and reads v2 and v1: a v1 document (one with no apiVersion) is converted as it is loaded, so a deployment moves on its own schedule. Configuration and policy are immutable for an instance: a change is a new instance (a rollout on Kubernetes, a new configuration layer on Lambda). What stays live is credentials and state.
Layering happens only when a policy is rendered (`sluisctl policy render`, Render); a process loads exactly one policy document.
Secrets are never in a document. Telemetry is not here at all; it is OpenTelemetry's own environment (OTEL_*).
The types are written by hand and the schemas are generated from schema/ into schemas/config/, which is committed; a test holds the two files to one another, and a second holds each type to its schema. The decision is docs/decisions/0032-one-configuration-file-one-binary-one-chart.md and, for the shared rules, truvity/policy 0002 and 0006.
Index ¶
- Constants
- Variables
- func APIVersion(document string) string
- func CheckCloudflare(cf *Cloudflare, p *PolicyDocument) error
- func CheckCloudflareMinterRef(ref string) error
- func Command(command, schema string, args []string, out io.Writer) (file string, done bool, err error)
- func IsBackup(file string) bool
- func IsGoogle(file string) bool
- func IsSluis(file string) bool
- func Load[T Document](file string) (*T, error)
- func RefuseRetired(binary string, environ []string) error
- func Retired(binary string) map[string]string
- func RetiredKeys(document string) map[string]string
- func Validate(name string, doc any) error
- type AWSAccount
- type AWSFederation
- type AdapterChoice
- type Address
- type AgentLifetimes
- type AppsGitHub
- type AppsSlack
- type Audit
- type Backup
- type BackupRetention
- type BackupTarget
- type Cloudflare
- type CloudflareAccount
- type CloudflareGrant
- type CloudflarePreset
- type CloudflareRemote
- type CloudflareServe
- type Config
- type Console
- type ConsoleBackup
- type ControllerCommon
- type ControllerGitHub
- type ControllerSlack
- type Controllers
- type ControllersGitHub
- type ControllersSlack
- type DeclaredSecret
- type Directory
- type DirectoryWorkspace
- type Document
- type Duration
- type DynamoDB
- type Exchange
- type ExchangeGitHub
- type FederatedCluster
- type Forwarded
- type Freshness
- type GitHubApp
- type GitHubController
- type Google
- type GoogleOAuthClient
- type Lifetimes
- type Log
- type Login
- type ModuleRemote
- type ModuleRoute
- type ModuleServe
- type OAuthClient
- type OpenBaoAuth
- type Platform
- type PolicyApps
- type PolicyCloudflare
- type PolicyControllers
- type PolicyDocument
- func (d *PolicyDocument) AWS() AWSFederation
- func (d *PolicyDocument) AppRef(org string) string
- func (d *PolicyDocument) Cloudflare() *PolicyCloudflare
- func (d *PolicyDocument) Clusters() []FederatedCluster
- func (d *PolicyDocument) EnabledOrgs() []string
- func (d *PolicyDocument) EnabledWorkspaces() []string
- func (d *PolicyDocument) Encode() ([]byte, error)
- func (d *PolicyDocument) GitHubAppExported(id string) bool
- func (d *PolicyDocument) GitHubAppLabels(id string) map[string]string
- func (d *PolicyDocument) GitHubApps() []GitHubApp
- func (d *PolicyDocument) GitHubCatalogue() *catalogue.Catalogue
- func (d *PolicyDocument) GitHubOwners() []string
- func (d *PolicyDocument) LegacyAppEntries() int
- func (d *PolicyDocument) LinkAppName() string
- func (d PolicyDocument) MarshalYAML() (any, error)
- func (d *PolicyDocument) OrganisationAppName(org string) string
- func (d *PolicyDocument) RunnerLabels(tier, org string) map[string]string
- func (d *PolicyDocument) RunnerTiers() []string
- func (d *PolicyDocument) SlackCatalogue() *slackcatalogue.Catalogue
- func (d *PolicyDocument) Unconsumed() []string
- func (d *PolicyDocument) UnmarshalJSON(raw []byte) error
- func (d *PolicyDocument) Validate() error
- type PolicyExchange
- type PolicyRef
- type Ports
- type PortsBlob
- type PortsBlobCredentials
- type PortsBlobS3
- type Recovery
- type Roster
- type RosterAudit
- type RosterConsole
- type RosterConsoleAWS
- type RosterConsoleAuth
- type SecretLocation
- type Secrets
- type Serve
- type Service
- type SigningKey
- type SigningKeyKMS
- type SigningKeyKMSAlg
- type SigningKeyKMSWrapped
- type SigningKeyVerifyOnly
- type SlackController
- type Sluis
- type SluisBackup
- type SluisGoogle
- type Valkey
Constants ¶
const ( // BackupRoleBackup is the scheduled export, the default. BackupRoleBackup = "backup" // BackupRoleRestore is the restore function, which only an administrator or // the break-glass role may invoke. BackupRoleRestore = "restore" )
The roles of the backup module's zip. The binary is one; the document picks the function it is deployed as (docs/decisions/0072, point 10).
const ( BackupDefaultKeep = 7 BackupDefaultMaxAge = 30 * 24 * time.Hour // BackupMaxKeep bounds Keep: a rule of thousands is a typo. BackupMaxKeep = 1000 )
The retention defaults.
const ( // CloudflareMinLifetime is the shortest lifetime and rotation: the tick // is a minute at best on Lambda. CloudflareMinLifetime = time.Minute // CloudflareMaxLifetime is the longest a minted token lives. A short-lived // credential that outlives a day is a long-lived one under another name. CloudflareMaxLifetime = 24 * time.Hour )
The limits of a preset's two settings.
const ( AWSAlgES384 = "ES384" AWSAlgRS256 = "RS256" // MaxAWSMaxAge is the longest exchange.aws.maxAge may be: AWS lets a // token live an hour. MaxAWSMaxAge = time.Hour )
The algorithms an AWS account's outbound identity tokens are signed with.
const ( // SecretRecoveryPassword is the password of the recovery sign-in. SecretRecoveryPassword = "recovery-password" // SecretStateSecret is the sign-in state's secret of a KMS-signed issuer. SecretStateSecret = "state-secret" // SecretSignInClientID is the Google sign-in client's id. SecretSignInClientID = "signin-client-id" // SecretSignInClientSecret is the Google sign-in client's secret. SecretSignInClientSecret = "signin-client-secret" // SecretClient is a seeded confidential client's secret. SecretClient = "client-secret" // SecretWorkspaceKey is a declared workspace's service-account key. SecretWorkspaceKey = "workspace-key" // SecretMinter is a Cloudflare account's minter credential. SecretMinter = "cloudflare-minter" // SecretBlobCredentials is the S3-compatible blob store's credential document. SecretBlobCredentials = "blob-credentials" )
The kinds of a DeclaredSecret.
const ( SecretsLayoutV4 = "v4" SecretsLayoutV5 = "v5" )
The values of Secrets.Layout.
const BackupAPIVersion = Group + "/sluis-backup/v1"
BackupAPIVersion is the apiVersion of the backup module's document.
const BackupDefaultIdentity = "restore-identity"
BackupDefaultIdentity is the restore identity's secret when backup.identity names none.
const EnvConfig = "SLUIS_CONFIG"
EnvConfig is the variable that names the service document when no --config is given.
const GoogleAPIVersion = Group + "/sluis-google/v1"
GoogleAPIVersion is the apiVersion of the Google module's document.
const Group = "sluis.truvity.github.io"
Group is the group of this repository's document kinds: an apiVersion is `sluis.truvity.github.io/<document>/v<N>`.
Variables ¶
var ( // CloudflareNamePattern is the name of a preset or an account: a DNS label. CloudflareNamePattern = regexp.MustCompile(`^[a-z0-9]([a-z0-9-]{0,30}[a-z0-9])?$`) )
Functions ¶
func APIVersion ¶ added in v1.62.0
APIVersion is the apiVersion this build writes for one document: `sluis` (v3), `sluis-backup` and `sluis-google` (v1), or `serve`, `controller-github`, `controller-slack` or `policy` (v2).
func CheckCloudflare ¶ added in v1.74.0
func CheckCloudflare(cf *Cloudflare, p *PolicyDocument) error
CheckCloudflare holds the policy's grants to the service document's presets: a grant for a preset that does not exist would read as a right nobody can use.
func CheckCloudflareMinterRef ¶ added in v1.74.0
CheckCloudflareMinterRef refuses a minter address that is not below internal/.
func Command ¶
func Command(command, schema string, args []string, out io.Writer) (file string, done bool, err error)
Command reads one subcommand's command line, which is `--config <file>` and nothing else but `--version` and `--help`; with no --config, SLUIS_CONFIG names the file. command is what the person typed to get here ("sluis serve"), and schema names the document it reads: schemas/config/<schema>.schema.json. A flag that overrides a key, or stands in for one, is a second source of truth: the service document, and the policy document it names, are the whole of the configuration.
It returns the file to read. done is true when the command line asked for something answered here (the version, the help) and the process should stop without error.
func IsBackup ¶ added in v1.75.0
IsBackup reports whether the file is the backup module's document, by its apiVersion alone.
func IsGoogle ¶ added in v1.76.0
IsGoogle reports whether the file is the Google module's document, by its apiVersion alone.
func IsSluis ¶ added in v1.63.0
IsSluis reports whether the file is the one service document (v3), by its apiVersion alone. A file that cannot be read is not: the loader reports it.
func Load ¶ added in v1.62.0
Load reads one document from a file, holds it to its schema and decodes it, through truvity/policy's versioned loader (config.LoadKind): a binary reads its documents' version N and N-1.
A v2 document is validated and decoded as it stands, after a key v2 retired is refused with a message saying where it went. A v1 document (no apiVersion) is held to the v1 schema it was written against and converted: what v1 kept in a service document and v2 keeps in the policy document is remembered, and PolicyOf reads it from the files v1 named.
func RefuseRetired ¶
RefuseRetired is the start-up check: it fails when the environment still holds a variable the subcommand no longer reads, naming each with what replaces it. environ is os.Environ's shape.
func Retired ¶
Retired returns, for one binary, every retired variable and what replaces it. The documentation's migration table is this, and a test holds them together.
func RetiredKeys ¶ added in v1.62.0
RetiredKeys returns, for one document, every key v2 retired and where it went.
Types ¶
type AWSAccount ¶ added in v1.62.0
type AWSAccount struct {
Account string `yaml:"account"`
Name string `yaml:"name"`
Issuer string `yaml:"issuer"`
JWKSURI string `yaml:"jwksUri,omitempty"`
OrgID string `yaml:"orgId,omitempty"`
Algs []string `yaml:"algs,omitempty"`
}
AWSAccount is one account's row.
type AWSFederation ¶ added in v1.62.0
type AWSFederation struct {
// Audience the role must request from sts:GetWebIdentityToken.
// Required whenever an account is listed: it is the trust boundary.
Audience string `yaml:"audience,omitempty"`
// MaxAge refuses a token whose `iat` is older. Default 5m, at most 1h.
MaxAge *Duration `yaml:"maxAge,omitempty"`
// Accounts are the trusted accounts.
Accounts []AWSAccount `yaml:"accounts,omitempty"`
}
AWSFederation is the AWS accounts whose roles may exchange their outbound identity federation token.
type AdapterChoice ¶ added in v1.58.0
type AdapterChoice struct {
Adapter string `json:"adapter"`
Settings map[string]any `json:"settings,omitempty"`
}
AdapterChoice names the adapter of one concern and its settings.
type Address ¶
type Address struct {
Address string `json:"address"`
}
Address is a TCP listener: host:port, an empty host binding every interface. It is the shared shape of truvity/policy's fragments/listen.json and probes.json.
type AgentLifetimes ¶ added in v1.69.0
type AgentLifetimes struct {
Refresh *Duration `json:"refresh,omitempty"`
Absolute *Duration `json:"absolute,omitempty"`
Access *Duration `json:"access,omitempty"`
}
AgentLifetimes are the agent class's own lifetimes (docs/decisions/0040-agent-class-sessions.md): its idle limit, its absolute limit from `auth_time`, and the mandatory cap on its access and ID tokens. A pointer is "not set", which is the default.
type AppsGitHub ¶ added in v1.62.0
type AppsGitHub struct {
// Apps is every GitHub App the installation declares, of every purpose:
// the link App, the catalogue Apps an operator creates and installs from
// the console, and the runner tiers an operator may create an App for.
Apps []GitHubApp `yaml:"apps,omitempty"`
// RunnerTiers is DEPRECATED, read for one release: each tier is a
// runner entry of Apps.
RunnerTiers []string `yaml:"runnerTiers,omitempty"`
// Catalogue is DEPRECATED, read for one release: each App is a catalogue
// entry of Apps.
Catalogue []catalogue.App `yaml:"catalogue,omitempty"`
// contains filtered or unexported fields
}
AppsGitHub is the GitHub Apps an operator may make.
type AppsSlack ¶ added in v1.62.0
type AppsSlack struct {
// Catalogue is every catalogue Slack App.
Catalogue []slackcatalogue.App `yaml:"catalogue,omitempty"`
}
AppsSlack is the Slack Apps an operator may make.
type Audit ¶
type Audit struct {
Writer string `json:"writer,omitempty"`
TokenFile string `json:"tokenFile,omitempty"`
QueryURL string `json:"queryURL,omitempty"`
Audience string `json:"audience,omitempty"`
ForwardedForTrustedHops int `json:"forwardedForTrustedHops,omitempty"`
}
Audit is the audit installation this process records to.
type Backup ¶ added in v1.75.0
type Backup struct {
// Role is [BackupRoleBackup] (the default) or [BackupRoleRestore].
Role string `json:"role,omitempty"`
// Recipients are the age X25519 public keys (age1...) every backup is
// encrypted to. The backup role requires at least one.
Recipients []string `json:"recipients,omitempty"`
// Identity names the restore role's secret that holds the age identity
// (AGE-SECRET-KEY-1...): internal/backup/<identity> in the secret store,
// [BackupDefaultIdentity] when unset.
Identity string `json:"identity,omitempty"`
// Key and Region were the KMS archive key of format 1. Deprecated: they
// are accepted for one release and ignored.
Key *keys.Entry `json:"key,omitempty"`
Region string `json:"region,omitempty"`
// Target is the bucket the archive is written to.
Target BackupTarget `json:"target"`
// Retention is how many backups are kept and for how long.
Retention *BackupRetention `json:"retention,omitempty"`
}
Backup is `backup`.
type BackupRetention ¶ added in v1.75.0
type BackupRetention struct {
// Keep is how many of the newest completed backups are always kept.
Keep *int `json:"keep,omitempty"`
// MaxAge is how old a backup beyond Keep may be before it is deleted.
MaxAge *Duration `json:"maxAge,omitempty"`
}
BackupRetention is the retention rule of Backup.Retention.
type BackupTarget ¶ added in v1.75.0
type BackupTarget struct {
Bucket string `json:"bucket"`
// Prefix is put before `backup/<installation>/` in the bucket.
Prefix string `json:"prefix,omitempty"`
Region string `json:"region,omitempty"`
// KMSKey is the SSE-KMS key of every write; unset leaves the bucket's own
// default encryption.
KMSKey string `json:"kmsKey,omitempty"`
Endpoint string `json:"endpoint,omitempty"`
PathStyle bool `json:"pathStyle,omitempty"`
// Checksum is the integrity header of every upload: sha256 (the default),
// md5 (Content-MD5) or none, for a store that refuses SHA-256.
Checksum string `json:"checksum,omitempty"`
}
BackupTarget is the S3 (or S3-compatible) bucket of the archive. Credentials are the platform's: the function's role.
type Cloudflare ¶ added in v1.74.0
type Cloudflare struct {
// Accounts are the Cloudflare accounts sluis mints in, by the name presets
// use.
Accounts map[string]CloudflareAccount `json:"accounts,omitempty"`
// Presets are what may be minted, by name.
Presets map[string]CloudflarePreset `json:"presets,omitempty"`
// ForbiddenPermissionGroups ADD to the built-in list of permission groups
// a prototype may never grant (token admin, billing, account settings,
// memberships, Access identity providers), by the name Cloudflare lists
// them under. They cannot remove from it: nothing in a document shortens
// the built-in list.
ForbiddenPermissionGroups []string `json:"forbiddenPermissionGroups,omitempty"`
// Tick is how often the rotation looks at the presets: the schedule's
// interval on Lambda (the library fills it from CloudflareRotation when it
// is unset), a minute for the Kubernetes loop. A credential rotates up to
// one Tick after its preset's `rotation`, so the console calls one overdue
// only past `rotation + tick`. Zero means a minute.
Tick Duration `json:"tick,omitempty"`
// Remote is where the minter is when it is not this process: the on-demand
// exchange then calls the Cloudflare module there, and this process holds no
// account and no preset.
Remote *CloudflareRemote `json:"remote,omitempty"`
// Serve makes the Cloudflare module answer other modules' calls: on
// Kubernetes a listener that verifies the caller's projected token, on
// Lambda the function's `rpc` events (docs/decisions/0071).
Serve *CloudflareServe `json:"serve,omitempty"`
}
Cloudflare is `cloudflare`: sluis as the STS for Cloudflare API tokens and R2 credentials (docs/guides/sluis/cloudflare-tokens.md). An account names the minter credential sluis holds; a preset names a disabled prototype token in that account whose policies and condition are the rights a minted token has.
func (*Cloudflare) AccountNames ¶ added in v1.74.0
func (c *Cloudflare) AccountNames() []string
AccountNames are the accounts' names, sorted.
func (*Cloudflare) PresetNames ¶ added in v1.74.0
func (c *Cloudflare) PresetNames() []string
PresetNames are the presets' names, sorted.
func (*Cloudflare) PresetOf ¶ added in v1.74.0
func (c *Cloudflare) PresetOf(name string) (CloudflarePreset, bool)
PresetOf is a preset by name. A nil section has none.
func (*Cloudflare) Validate ¶ added in v1.74.0
func (c *Cloudflare) Validate() error
Validate holds the section to what its schema cannot say. A nil section is valid: Cloudflare is off.
type CloudflareAccount ¶ added in v1.74.0
type CloudflareAccount struct {
// ID is the account id.
ID string `json:"id"`
// Minter is the internal address of the minter credential, a
// cloudflare-minter/v1 document: an account token that holds Account API
// Tokens Read and Edit and nothing else.
Minter string `json:"minter"`
}
CloudflareAccount is one Cloudflare account.
type CloudflareGrant ¶ added in v1.74.0
type CloudflareGrant struct {
// Group is an internal group of the policy (a person group, or a declared CI
// job group); every holder may ask.
Group string `yaml:"group,omitempty" json:"group,omitempty"`
// Presets are the presets the row opens.
Presets []string `yaml:"presets" json:"presets"`
}
CloudflareGrant is one row of grants.
type CloudflarePreset ¶ added in v1.74.0
type CloudflarePreset struct {
// Account is a key of Accounts.
Account string `json:"account"`
// Prototype is the id of the DISABLED account token whose policies and
// condition every minted token copies.
Prototype string `json:"prototype"`
// Description says what the preset is for; the console and sluisctl show it.
Description string `json:"description"`
// Lifetime is how long a minted token lives (its expires_on).
Lifetime Duration `json:"lifetime"`
// Rotation is how often the stored token is replaced. Shorter than Lifetime.
Rotation Duration `json:"rotation"`
// Endpoint, when set, makes this an R2 preset: the S3 endpoint of the
// account (and jurisdiction) the credentials are for.
Endpoint string `json:"endpoint,omitempty"`
}
CloudflarePreset is one thing sluis mints.
func (CloudflarePreset) R2 ¶ added in v1.74.0
func (p CloudflarePreset) R2() bool
R2 reports whether the preset hands out R2 (S3) credentials.
type CloudflareRemote ¶ added in v1.75.0
type CloudflareRemote struct {
// Function is the module's Lambda function, name or ARN; it is invoked
// through its `live-issuer` alias.
Function string `json:"function,omitempty"`
// URL is the module's Service, called with the pod's projected token.
URL string `json:"url,omitempty"`
// Audience is the audience of that token; the module's name when unset.
Audience string `json:"audience,omitempty"`
// TokenFile is where the projected token is mounted.
TokenFile string `json:"tokenFile,omitempty"`
}
CloudflareRemote is the Cloudflare module in another process: a Lambda function or a Kubernetes Service (docs/decisions/0071).
func (*CloudflareRemote) Target ¶ added in v1.76.0
func (r *CloudflareRemote) Target() ModuleRemote
Target is the Cloudflare module's remote as a ModuleRemote.
type CloudflareServe ¶ added in v1.75.0
type CloudflareServe struct {
// Address is the listener on Kubernetes: host:port. Lambda ignores it.
Address string `json:"address,omitempty"`
// Audience is the audience a caller's projected token must have been
// minted for; the module's name when unset.
Audience string `json:"audience,omitempty"`
// Issuers are the subjects of the issuer's ServiceAccount
// (`system:serviceaccount:<namespace>:<name>`) that may call the listener
// on Kubernetes; each is both the issuer class (the mint) and the console
// class. Required by the listener; Lambda ignores it.
Issuers []string `json:"issuers,omitempty"`
}
CloudflareServe is where the Cloudflare module answers other modules.
type Config ¶ added in v1.62.0
type Config[S Service] struct { Service *S // Policy is nil when the service document names none and no fallback was // given. Policy *PolicyDocument }
Config is one process's whole configuration, by section: the service document it was started with and the policy document that names. Nothing is overlaid: each section is one document.
func LoadConfig ¶ added in v1.62.0
LoadConfig reads a process's service document and the policy document it names. fallback is the access model's tables a process decides by when the document names no policy (the service's built-in two groups); nil leaves the policy nil.
type Console ¶
type Console struct {
Origin string `json:"origin,omitempty"`
Client string `json:"client,omitempty"`
// AWSAudience is the audience an AWS role's web identity token must be
// minted for to be a bearer at the console: its OWN, distinct from
// `exchange`'s, so a token for one door is no proof at the other.
AWSAudience string `json:"awsAudience,omitempty"`
// Backup connects the console's Backups page to the backup module and
// the restore function (docs/decisions/0071). Unset has no page.
Backup *ConsoleBackup `json:"backup,omitempty"`
}
Console is where the console is published, for the sign-in that starts there.
type ConsoleBackup ¶ added in v1.75.0
type ConsoleBackup struct {
// Function and URL name the backup module: exactly one of the two.
Function string `json:"function,omitempty"`
URL string `json:"url,omitempty"`
// RestoreFunction and RestoreURL name the restore function: at most one
// of the two. Without either the page says there is none.
RestoreFunction string `json:"restoreFunction,omitempty"`
RestoreURL string `json:"restoreURL,omitempty"`
// Audience is the audience of the projected token a Service call
// carries; each module's name when unset.
Audience string `json:"audience,omitempty"`
// TokenFile is where that token is mounted.
TokenFile string `json:"tokenFile,omitempty"`
}
ConsoleBackup is where the backup module and the restore function are when the console calls them as the caller class `console`: a Lambda function (through its `live-console` alias) or a Kubernetes Service each. The console only reads from them.
func (*ConsoleBackup) Validate ¶ added in v1.75.0
func (b *ConsoleBackup) Validate() error
Validate holds `console.backup` to what its schema cannot say. A nil section is valid: the console has no Backups page.
type ControllerCommon ¶ added in v1.63.0
type ControllerCommon struct {
// ConsoleURL is the console's API. Unset is the document's `publicURL`.
ConsoleURL string `json:"consoleURL,omitempty"`
TokenFile string `json:"tokenFile,omitempty"`
// Console says how the controller proves itself to the console when the
// pod's token file is not the way (AWS Lambda).
Console *RosterConsole `json:"console,omitempty"`
RecordsDir string `json:"recordsDir,omitempty"`
Interval *Duration `json:"interval,omitempty"`
}
ControllerCommon is what both controllers' sections share.
type ControllerGitHub ¶
ControllerGitHub is the configuration of `sluis controller github`.
type ControllerSlack ¶
ControllerSlack is the configuration of `sluis controller slack`.
type Controllers ¶ added in v1.63.0
type Controllers struct {
GitHub *GitHubController `json:"github,omitempty"`
Slack *SlackController `json:"slack,omitempty"`
}
Controllers are the controllers the one process runs. A nil one is off.
type ControllersGitHub ¶ added in v1.62.0
type ControllersGitHub struct {
// EnabledOrgs are the organisations it changes. Each must be bound
// by the policy's github table.
EnabledOrgs []string `yaml:"enabledOrgs,omitempty"`
// AppRefs names, by organisation, the catalogue App whose key the
// organisation's record refers to (`app_ref`). Optional: a record that
// already names an App keeps it, and an entry overrides it or declares
// an organisation anew.
AppRefs map[string]string `yaml:"appRefs,omitempty"`
// AppNames names, by organisation, the App this service creates for
// it when an operator connects it (the organisation App's name on
// GitHub). Optional: an organisation with no entry is created as
// <org>-access-roster. GitHub's limit is 34 characters.
AppNames map[string]string `yaml:"appNames,omitempty"`
}
ControllersGitHub is what the GitHub controller may change.
type ControllersSlack ¶ added in v1.62.0
type ControllersSlack struct {
// EnabledWorkspaces are the workspaces it changes, by the policy's
// key. Each must be declared by the policy's slack table.
EnabledWorkspaces []string `yaml:"enabledWorkspaces,omitempty"`
}
ControllersSlack is what the Slack controller may change.
type DeclaredSecret ¶ added in v1.75.0
type DeclaredSecret struct {
// Kind is one of the Secret* constants.
Kind string
// Subject is what the secret belongs to: a Google provider, a client id, a
// workspace id, a Cloudflare account; empty when there is one of the kind.
Subject string
// Name is where layout v4 keeps it. For a Ref it is the internal address
// (`internal/<module>/<name>`) the document gives, the same in every
// layout; otherwise it is the secret's name below `internal/config/`.
Name string
// Ref says Name is an address and not a name.
Ref bool
}
DeclaredSecret is one secret a service document and its policy declare, and the installation must therefore hold: it is read at the first request that needs it, so a missing or mistyped one is found by a check at deploy time or by a person at the first sign-in.
Only what a document DECLARES is here. What sluis creates at run time (the console's session key, a GitHub or Slack App's credential, which the console writes when an operator makes the App) is not: no document names it before it exists.
func DeclaredSecrets ¶ added in v1.75.0
func DeclaredSecrets(doc *Serve, pol *PolicyDocument) []DeclaredSecret
DeclaredSecrets is the set of secrets doc and pol declare, sorted by kind, subject and name, without repeats. pol may be nil. It reads nothing, and no value is ever in it.
The rules:
- the recovery password, when `recovery.passwordSecret` names it and `recovery.enabled` is not false;
- the state secret, when `signingKey.kms` or `signingKey.kmsWrapped` is set (a file signer has none);
- the Google sign-in client: its secret, and its id unless `oauthClient.id` gives it;
- the secret of every confidential client of the policy that names one (a generated secret is the issuer's to make);
- the key of every declared workspace;
- the minter of every Cloudflare account, and the S3 credentials document `ports.blob.s3.credentialsRef` names.
type Directory ¶ added in v1.62.0
type Directory struct {
Workspaces []DirectoryWorkspace `json:"workspaces,omitempty"`
}
Directory is the corporate directories the deployment declares, which the service adopts at start (the console connects the others).
type DirectoryWorkspace ¶ added in v1.62.0
type DirectoryWorkspace struct {
ID string `json:"id,omitempty"`
Backend string `json:"backend"`
Admin string `json:"admin"`
KeySecret string `json:"keySecret"`
Serve []string `json:"serve,omitempty"`
SyncGroups []string `json:"syncGroups,omitempty"`
}
DirectoryWorkspace is one declared workspace. It is deliberately thin: an id the deployment may know, a backend, an admin to act as, and where the credential is. Everything else, the domains and the tenant's own id, is discovered.
type Document ¶ added in v1.62.0
type Document interface {
Sluis | Serve | ControllerGitHub | ControllerSlack | PolicyDocument
}
Document is what Load reads: a service document or the policy document.
type Duration ¶
Duration is a time span as the file spells it: a Go duration string such as "30s", "2m" or "168h".
type DynamoDB ¶
type DynamoDB struct {
Table string `json:"table,omitempty"`
// Tables is layout v5: the table of each module, by module name
// (`secrets.layout: v5`). Exclusive with Table.
Tables map[string]string `json:"tables,omitempty"`
Region string `json:"region,omitempty"`
Endpoint string `json:"endpoint,omitempty"`
Create bool `json:"create,omitempty"`
}
DynamoDB is where the `dynamodb` adapter keeps State, the transitional Index and the Trigger: one table. Credentials are the platform's (Pod Identity, IRSA, a Lambda role), never configured.
type Exchange ¶
type Exchange struct {
Audience string `json:"audience,omitempty"`
}
Exchange is what the token exchange verifies workloads against.
type ExchangeGitHub ¶ added in v1.62.0
type ExchangeGitHub struct {
// Owners are the organisations whose repositories' CI tokens are
// verified. None verifies none: an empty list would admit every
// repository there is.
Owners []string `yaml:"owners,omitempty"`
}
ExchangeGitHub is whose GitHub Actions tokens are verified.
type FederatedCluster ¶ added in v1.62.0
type FederatedCluster struct {
// Name is the estate's own word for the cluster; it becomes the
// cluster in a `service_account` matcher and in a minted token's
// subject.
Name string `yaml:"name"`
// Issuer is the `iss` its ServiceAccount tokens carry.
Issuer string `yaml:"issuer"`
// JWKSURI is where its keys are. Empty discovers it from the issuer.
JWKSURI string `yaml:"jwksUri,omitempty"`
}
FederatedCluster is one cluster's row.
type Forwarded ¶
type Forwarded struct {
Issuer string `json:"issuer,omitempty"`
Audience string `json:"audience,omitempty"`
EmailHeader string `json:"emailHeader,omitempty"`
}
Forwarded is a sign-in an authenticating proxy in front of the console has already done.
type Freshness ¶
type Freshness struct {
RefreshInterval *Duration `json:"refreshInterval,omitempty"`
FreshnessWindow *Duration `json:"freshnessWindow,omitempty"`
ProbeInterval *Duration `json:"probeInterval,omitempty"`
}
Freshness is how the directory's snapshot is kept current.
type GitHubApp ¶ added in v1.75.0
type GitHubApp struct {
// ID is the App's key in storage: `link`, a catalogue App's own id, or
// `runner-<tier>` (`runner-<tier>-<org>` with an `org`), which a runner entry
// may leave out.
ID string `yaml:"id,omitempty"`
Purpose appid.Purpose `yaml:"purpose"`
Labels map[string]string `yaml:"labels,omitempty"`
// Export places the installed App's key at external/github/<id>. A runner
// App is always exported.
Export bool `yaml:"export,omitempty"`
// Org is the organisation a catalogue App is created under, or a runner
// entry's only organisation.
Org string `yaml:"org,omitempty"`
Tier string `yaml:"tier,omitempty"`
// Name is the App's name on GitHub, at most 34 characters: a catalogue
// App's (default <org>-<id>) or the link App's (default
// <org>-access-roster-link).
Name string `yaml:"name,omitempty"`
// The rest is a catalogue App's alone.
Description string `yaml:"description,omitempty"`
Public bool `yaml:"public,omitempty"`
Permissions map[string]string `yaml:"permissions,omitempty"`
Events []string `yaml:"events,omitempty"`
Webhook *catalogue.Webhook `yaml:"webhook,omitempty"`
Installation string `yaml:"installation,omitempty"`
Grants []catalogue.Grant `yaml:"grants,omitempty"`
}
GitHubApp is one declared GitHub App of any purpose: the one list `apps.github.apps` (ADR 0072) that replaces the separate catalogue and runner tiers.
A `catalogue` App carries the whole of catalogue.App. A `runner` entry declares a tier an operator may make a runner App for, in one organisation (`org`) or in any (no `org`), and its Apps are `runner-<tier>-<org>`. The `link` entry is the App that links a person's GitHub account; it has the id `link` and declares its labels, whether it is exported, the owner `org` and a `name` for the App it is created as.
type GitHubController ¶ added in v1.63.0
type GitHubController struct {
ControllerCommon
AppsDir string `json:"appsDir,omitempty"`
}
GitHubController is `controllers.github`.
type Google ¶ added in v1.76.0
type Google struct {
// Workspaces are the workspaces the deployment declares.
Workspaces []DirectoryWorkspace `json:"workspaces,omitempty"`
// OAuthClient is the client that reopens a workspace connected by consent,
// and the one the console's consent and the issuer's sign-in use.
OAuthClient *GoogleOAuthClient `json:"oauthClient,omitempty"`
// PublicURL is where a browser reaches the issuer, including its mount:
// the consent and sign-in redirect URIs are built from it. The same value
// as the issuer's `publicURL`.
PublicURL string `json:"publicURL,omitempty"`
// RefreshInterval, FreshnessWindow and ProbeInterval are the hub's knobs.
RefreshInterval *Duration `json:"refreshInterval,omitempty"`
FreshnessWindow *Duration `json:"freshnessWindow,omitempty"`
ProbeInterval *Duration `json:"probeInterval,omitempty"`
}
Google is `google`.
type GoogleOAuthClient ¶ added in v1.76.0
type GoogleOAuthClient struct {
ID string `json:"id,omitempty"`
Provider string `json:"provider,omitempty"`
}
GoogleOAuthClient is `google.oauthClient`: the id (not a secret) or the provider whose secrets hold it, and the provider whose client-secret it is.
type Lifetimes ¶
type Lifetimes struct {
Token *Duration `json:"token,omitempty"`
Refresh *Duration `json:"refresh,omitempty"`
Absolute *Duration `json:"absolute,omitempty"`
Hold *Duration `json:"hold,omitempty"`
Session *Duration `json:"session,omitempty"`
// Agent is `lifetimes.agent`: how long the refresh chains of clients
// the policy marks `session: agent` live.
Agent *AgentLifetimes `json:"agent,omitempty"`
}
Lifetimes are how long what the issuer hands out lives. A pointer is "not set": zero is a value a file can state, and the absolute lifetime refuses it.
type Log ¶
type Log struct {
Level string `json:"level,omitempty"`
}
Log is the shared shape of truvity/policy's fragments/log.json.
type Login ¶
type Login struct {
Directory *bool `json:"directory,omitempty"`
SignOutURL string `json:"signOutURL,omitempty"`
Forwarded *Forwarded `json:"forwarded,omitempty"`
}
Login is how a person signs in to the console.
type ModuleRemote ¶ added in v1.76.0
type ModuleRemote struct {
// Function is the module's Lambda function, name or ARN; it is invoked
// through the `live-<class>` alias of the caller's class.
Function string `json:"function,omitempty"`
// URL is the module's Service, called with the pod's projected token.
URL string `json:"url,omitempty"`
// Audience is the audience of that token; the module's name when unset.
Audience string `json:"audience,omitempty"`
// TokenFile is where the projected token is mounted;
// /var/run/secrets/sluis/<module>/token when unset.
TokenFile string `json:"tokenFile,omitempty"`
}
ModuleRemote is a module in another process: a Lambda function or a Kubernetes Service (docs/decisions/0071). It has the shape of CloudflareRemote.
type ModuleRoute ¶ added in v1.76.0
type ModuleRoute struct {
// Remote is where the module is when it is not this process. Unset keeps
// the module in this process.
Remote *ModuleRemote `json:"remote,omitempty"`
// Serve makes the module answer other modules' calls on Kubernetes: a
// listener that verifies the caller's projected ServiceAccount token. Only
// the module's own document sets it (`github.serve` for the GitHub
// module, `slack.serve` for the Slack one).
Serve *ModuleServe `json:"serve,omitempty"`
}
ModuleRoute is the section of a module that is not its own settings: `github`, `slack` and `google` each carry one. It holds where the module is when it is not this process.
func (*ModuleRoute) Validate ¶ added in v1.76.0
func (r *ModuleRoute) Validate(module string) error
Validate holds the section to what its schema cannot say. A nil section, or one with no remote, keeps the module in this process.
type ModuleServe ¶ added in v1.76.0
type ModuleServe struct {
// Address is the listener: host:port. :8081 when unset.
Address string `json:"address,omitempty"`
// Audience is the audience a caller's projected token must have been minted
// for; the module's name when unset.
Audience string `json:"audience,omitempty"`
// Issuers are the subjects of the issuer's ServiceAccount
// (`system:serviceaccount:<namespace>:<name>`). Each is both the issuer
// class (`mint_installation`) and the console class (`*.console.*`); a
// token of any other subject is a 401. At least one is required.
Issuers []string `json:"issuers,omitempty"`
}
ModuleServe is where the GitHub or Slack module answers the issuer on Kubernetes (docs/decisions/0071): `POST /rpc` with a bearer that a TokenReview accepts for Audience and that belongs to one of Issuers. Lambda ignores it: the function answers `rpc` events and IAM decides who invokes it.
func (*ModuleServe) Validate ¶ added in v1.76.0
func (s *ModuleServe) Validate(at string) error
Validate holds the listener to what its schema cannot say.
type OAuthClient ¶
type OAuthClient struct {
ID string `json:"id,omitempty"`
// Provider names the client's two secrets,
// providers/google/<provider>/client-id and .../client-secret. The
// id may instead be ID, which is not a secret.
Provider string `json:"provider,omitempty"`
SecretName string `json:"secretName,omitempty"`
IDKey string `json:"idKey,omitempty"`
SecretKey string `json:"secretKey,omitempty"`
}
OAuthClient is the client registered once with the directory backend. Its secret is a file or a declared variable, never a value.
type OpenBaoAuth ¶
type OpenBaoAuth struct {
Method string `json:"method,omitempty"`
Mount string `json:"mount,omitempty"`
Role string `json:"role,omitempty"`
TokenFile string `json:"tokenFile,omitempty"`
}
OpenBaoAuth is how the service logs in to OpenBao inside each namespace it writes to: the kubernetes or the jwt auth method, as a role, with a token read from a file.
type Platform ¶ added in v1.58.0
type Platform struct {
AWS bool `json:"aws,omitempty"`
Kubernetes bool `json:"kubernetes,omitempty"`
OpenBao bool `json:"openbao,omitempty"`
Runtime string `json:"runtime,omitempty"`
Replicas int `json:"replicas,omitempty"`
}
Platform is the answers to the questions that pick a preset: what the installation has to build on (docs/concepts/sluis/ports.md, "Adapters").
type PolicyApps ¶ added in v1.62.0
type PolicyApps struct {
GitHub *AppsGitHub `yaml:"github,omitempty"`
Slack *AppsSlack `yaml:"slack,omitempty"`
}
PolicyApps is what an operator may make on the console.
func (*PolicyApps) FoldLegacy ¶ added in v1.75.0
func (a *PolicyApps) FoldLegacy()
FoldLegacy folds the retired sections of the GitHub Apps into the list. The sections are read for one release (removed in v1.77, like the layout they come with); the canonical document `sluisctl policy render` writes carries the list only. How many entries it made is PolicyDocument.LegacyAppEntries, for the process to warn on.
type PolicyCloudflare ¶ added in v1.74.0
type PolicyCloudflare struct {
// Grants say which presets the holders of a group may have a token for. A
// CI job is a group like any other: the policy declares it as a group with
// `github` matchers (repository, ref, event, job_workflow_ref), and the
// verified token is evaluated against them by the same group evaluation
// as everything else.
Grants []CloudflareGrant `yaml:"grants,omitempty" json:"grants,omitempty"`
}
PolicyCloudflare is the policy document's `cloudflare` section: who may ask for which preset.
func (*PolicyCloudflare) Allows ¶ added in v1.74.0
func (c *PolicyCloudflare) Allows(preset string, groups []string) bool
Allows reports whether a holder of groups may ask for preset.
func (*PolicyCloudflare) PresetsForGroups ¶ added in v1.74.0
func (c *PolicyCloudflare) PresetsForGroups(groups []string) []string
PresetsForGroups are the presets a holder of any of groups may ask for, sorted and without repeats.
type PolicyControllers ¶ added in v1.62.0
type PolicyControllers struct {
GitHub *ControllersGitHub `yaml:"github,omitempty"`
Slack *ControllersSlack `yaml:"slack,omitempty"`
}
PolicyControllers is what each controller may change. Everything else the policy binds is derived and reported, and left alone.
type PolicyDocument ¶ added in v1.62.0
type PolicyDocument struct {
// APIVersion is sluis.truvity.github.io/policy/v2. A v1 policy file (`version:
// 1`, or an access document) is converted as it is loaded.
APIVersion string
// Policy is the access model's tables. Its Version is always 1: the
// document's own version is APIVersion.
Policy policy.Policy
// Exchange is whom the token exchange trusts.
Exchange *PolicyExchange `yaml:"exchange,omitempty"`
// Apps is what an operator may make on the console.
Apps *PolicyApps `yaml:"apps,omitempty"`
// Controllers is what each controller may change.
Controllers *PolicyControllers `yaml:"controllers,omitempty"`
// CloudflareGrants is who may ask for which Cloudflare preset
// (`cloudflare.grants`); the presets are the service document's.
CloudflareGrants *PolicyCloudflare `yaml:"cloudflare,omitempty"`
}
PolicyDocument is the policy document: what an installation decides, in one file every process of it reads (`policy.file`).
Its tables are the access model's (package policy, docs/reference/sluis/policy.md), unchanged; beside them are the decisions that used to be spread over the service documents and the files they named:
exchange whom the token exchange trusts: the federated clusters, the
AWS accounts, the GitHub owners whose CI tokens are verified
apps what an operator may make: runner tiers, the GitHub and Slack
App catalogues
controllers what each controller may change (the dry-run gate)
It is rendered, never layered at run time: `sluisctl policy render` (and the Pulumi library) merge a directory of layers, access documents and fragments into one canonical document (Render), and a process reads that one file.
func NewPolicyDocument ¶ added in v1.62.0
func NewPolicyDocument(p policy.Policy) *PolicyDocument
NewPolicyDocument is a v2 document holding only the access model's tables.
func PolicyOf ¶ added in v1.62.0
func PolicyOf[S Service](svc *S, fallback *policy.Policy) (*PolicyDocument, error)
PolicyOf reads the policy document a service document names: its `policy.file`, or, for a converted v1 document, the files v1 named. With neither, fallback's tables, or nil.
func Render ¶ added in v1.62.0
func Render(path string) (*PolicyDocument, error)
Render builds the one canonical policy document from the layers a deployment declares, and holds it to every check the binary would: it is what `sluisctl policy render` and the Pulumi library call, and the only place layering happens. A process loads the document a render wrote, and nothing else.
path is a file or a directory. Every YAML file in a directory is one layer, read in name order, and each is one of:
- a policy file of v1 (`version: 1`): tables;
- an access document (`access:` and `overlay:`), reshaped into tables;
- a policy document fragment (`apiVersion: sluis.truvity.github.io/policy/v2`): tables and any of the sections, `exchange`, `apps`, `controllers`, `cloudflare`.
Tables merge by key and a key declared twice is an error naming the file, as they always have. Of the sections, a list concatenates and a list of names unions (the checks refuse a name or an id twice); a scalar declared by two layers is an error.
func (*PolicyDocument) AWS ¶ added in v1.62.0
func (d *PolicyDocument) AWS() AWSFederation
AWS is the AWS federation, empty when none is declared.
func (*PolicyDocument) AppRef ¶ added in v1.75.0
func (d *PolicyDocument) AppRef(org string) string
AppRef is the id of the App an organisation uses (`app_ref` of its record), or empty when the configuration names none.
func (*PolicyDocument) Cloudflare ¶ added in v1.74.0
func (d *PolicyDocument) Cloudflare() *PolicyCloudflare
Cloudflare is the policy's section, never nil.
func (*PolicyDocument) Clusters ¶ added in v1.62.0
func (d *PolicyDocument) Clusters() []FederatedCluster
Clusters are the federated clusters, or none.
func (*PolicyDocument) EnabledOrgs ¶ added in v1.62.0
func (d *PolicyDocument) EnabledOrgs() []string
EnabledOrgs are the organisations the GitHub controller changes.
func (*PolicyDocument) EnabledWorkspaces ¶ added in v1.62.0
func (d *PolicyDocument) EnabledWorkspaces() []string
EnabledWorkspaces are the workspaces the Slack controller changes.
func (*PolicyDocument) Encode ¶ added in v1.62.0
func (d *PolicyDocument) Encode() ([]byte, error)
Encode is the canonical document as YAML.
func (*PolicyDocument) GitHubAppExported ¶ added in v1.75.0
func (d *PolicyDocument) GitHubAppExported(id string) bool
GitHubAppExported reports whether the link or catalogue App with the id is declared `export: true`. A runner App is always exported and is not asked here.
func (*PolicyDocument) GitHubAppLabels ¶ added in v1.75.0
func (d *PolicyDocument) GitHubAppLabels(id string) map[string]string
GitHubAppLabels are the labels declared for the link or catalogue App with the id, or nil.
func (*PolicyDocument) GitHubApps ¶ added in v1.75.0
func (d *PolicyDocument) GitHubApps() []GitHubApp
GitHubApps are the declared GitHub Apps of every purpose, in declaration order.
func (*PolicyDocument) GitHubCatalogue ¶ added in v1.62.0
func (d *PolicyDocument) GitHubCatalogue() *catalogue.Catalogue
GitHubCatalogue is the catalogue Apps of the list, never nil.
func (*PolicyDocument) GitHubOwners ¶ added in v1.62.0
func (d *PolicyDocument) GitHubOwners() []string
GitHubOwners are the organisations whose CI tokens are verified.
func (*PolicyDocument) LegacyAppEntries ¶ added in v1.75.0
func (d *PolicyDocument) LegacyAppEntries() int
LegacyAppEntries is how many entries of apps.github.apps came from the retired runnerTiers and catalogue sections: nonzero means the document is to be moved to the list.
func (*PolicyDocument) LinkAppName ¶ added in v1.75.0
func (d *PolicyDocument) LinkAppName() string
LinkAppName is the name the link App is created with, or empty for the default (<owner>-access-roster-link).
func (PolicyDocument) MarshalYAML ¶ added in v1.62.0
func (d PolicyDocument) MarshalYAML() (any, error)
MarshalYAML writes the canonical document: apiVersion first, the tables as the access model writes them, then the sections. Map keys are sorted, so two renders of one policy are the same bytes.
func (*PolicyDocument) OrganisationAppName ¶ added in v1.75.0
func (d *PolicyDocument) OrganisationAppName(org string) string
OrganisationAppName is the name the organisation's App is created with (`controllers.github.appNames`), or empty for the default (<org>-access-roster).
func (*PolicyDocument) RunnerLabels ¶ added in v1.75.0
func (d *PolicyDocument) RunnerLabels(tier, org string) map[string]string
RunnerLabels are the labels of the runner App of a tier in an organisation: those of the entry for the tier in any organisation, and then those of the entry for this organisation, which win.
func (*PolicyDocument) RunnerTiers ¶ added in v1.62.0
func (d *PolicyDocument) RunnerTiers() []string
RunnerTiers are the tiers an operator may create a runner App for: those of the runner entries, each once.
func (*PolicyDocument) SlackCatalogue ¶ added in v1.62.0
func (d *PolicyDocument) SlackCatalogue() *slackcatalogue.Catalogue
SlackCatalogue is the Slack App catalogue, never nil.
func (*PolicyDocument) Unconsumed ¶ added in v1.62.0
func (d *PolicyDocument) Unconsumed() []string
Unconsumed is the access model's lint, with the GitHub catalogue's grants counted as consumers.
func (*PolicyDocument) UnmarshalJSON ¶ added in v1.62.0
func (d *PolicyDocument) UnmarshalJSON(raw []byte) error
UnmarshalJSON reads a document already held to its schema (JSON is YAML): what the versioned loader decodes into.
func (*PolicyDocument) Validate ¶ added in v1.62.0
func (d *PolicyDocument) Validate() error
Validate holds the document to what a schema cannot say: the access model's own rules, and every reference from a section to the tables or to another section. Everything is checked before a process starts, and the checks are the same wherever the document is read: the binary, `sluisctl policy render`, and the Pulumi library before it publishes one.
type PolicyExchange ¶ added in v1.62.0
type PolicyExchange struct {
// Clusters are the clusters whose ServiceAccount tokens are verified,
// each against the key set it publishes for itself.
Clusters []FederatedCluster `yaml:"clusters,omitempty"`
// AWS is the AWS accounts whose roles' outbound identity tokens are
// verified.
AWS *AWSFederation `yaml:"aws,omitempty"`
// GitHub is whose CI tokens are verified.
GitHub *ExchangeGitHub `yaml:"github,omitempty"`
}
PolicyExchange is whom the token exchange trusts. Nothing here is a secret: every row is a name and a URL.
type PolicyRef ¶ added in v1.62.0
type PolicyRef struct {
File string `json:"file,omitempty"`
}
PolicyRef names the one policy document a process decides by: the canonical document `sluisctl policy render` writes. It is read once, at start; a change is a new instance.
type Ports ¶
type Ports struct {
Adapter string `json:"adapter,omitempty"`
Blob *PortsBlob `json:"blob,omitempty"`
// DynamoDB is the table of the `dynamodb` adapter.
DynamoDB *DynamoDB `json:"dynamodb,omitempty"`
}
Ports chooses the adapter behind the storage ports of docs/concepts/sluis/ports.md.
Adapter picks the State, Index and Trigger (and, unless overridden below, the Blob). Blob replaces one port with an adapter that composes with any of them: State legacy with Blob s3 is valid.
type PortsBlob ¶
type PortsBlob struct {
Adapter string `json:"adapter,omitempty"`
S3 *PortsBlobS3 `json:"s3,omitempty"`
}
PortsBlob names the adapter behind the Blob port.
type PortsBlobCredentials ¶ added in v1.74.0
type PortsBlobCredentials struct {
// Preset is a key of `cloudflare.presets` with an `endpoint` (an R2
// preset).
Preset string `json:"preset"`
}
PortsBlobCredentials names the preset an S3-compatible store's credentials are minted from.
type PortsBlobS3 ¶
type PortsBlobS3 struct {
Bucket string `json:"bucket,omitempty"`
Prefix string `json:"prefix,omitempty"`
Region string `json:"region,omitempty"`
KMSKey string `json:"kmsKey,omitempty"`
Endpoint string `json:"endpoint,omitempty"`
PathStyle bool `json:"pathStyle,omitempty"`
// Checksum is the integrity header of every upload: sha256 (the
// default, x-amz-checksum-sha256), md5 (Content-MD5) or none, for a
// store that refuses SHA-256.
Checksum string `json:"checksum,omitempty"`
// CredentialsRef is the internal address (`internal/<kind>/<id>`) of
// the s3-credentials/v1 document the installation's secrets store
// holds for Endpoint. It needs Endpoint and the ssm secrets source.
CredentialsRef string `json:"credentialsRef,omitempty"`
// Credentials makes sluis mint its own R2 credentials from a
// `cloudflare.presets` entry instead of reading a static document. It
// is exclusive with CredentialsRef, which stays the simple default
// and needs no `cloudflare` section.
Credentials *PortsBlobCredentials `json:"credentials,omitempty"`
}
PortsBlobS3 is where the S3 Blob adapter keeps its objects. Credentials are the platform's (Pod Identity, IRSA, a Lambda role), never configured; an S3-compatible endpoint with no such identity names them by address (CredentialsRef), never by value.
type Recovery ¶
type Recovery struct {
Enabled *bool `json:"enabled,omitempty"`
ServiceAccount string `json:"serviceAccount,omitempty"`
Audience string `json:"audience,omitempty"`
// LoginSecret (`passwordSecret`) names the recovery password, for a hub that is not
// in a cluster: `recovery/password` in the layout.
LoginSecret string `json:"passwordSecret,omitempty"`
}
Recovery is the sign-in that needs no directory. A pointer for Enabled: unset is the hub's default (on) and the issuer's (off), as it has always been.
type Roster ¶
type Roster struct {
// APIVersion is the document's version: v2. A document without one is v1,
// which [Load] converts.
APIVersion string `json:"apiVersion"`
Release string `json:"release,omitempty"`
// Policy names the policy document: the bindings are its github or slack
// table, and its `controllers` section is what the controller may change.
Policy *PolicyRef `json:"policy"`
ConsoleURL string `json:"consoleURL"`
TokenFile string `json:"tokenFile,omitempty"`
// Console says how the controller proves itself to the console when the
// pod's token file is not the way (AWS Lambda).
Console *RosterConsole `json:"console,omitempty"`
RecordsDir string `json:"recordsDir,omitempty"`
Interval *Duration `json:"interval,omitempty"`
Log *Log `json:"log,omitempty"`
Ports *Ports `json:"ports,omitempty"`
// Platform, Preset and Adapters choose the adapters by name, per concern, as
// they do in the serve configuration; the Lambda controllers need them for
// the audit sink (`sqs`) and the state they share with the service.
Platform *Platform `json:"platform,omitempty"`
Preset string `json:"preset,omitempty"`
Adapters map[string]AdapterChoice `json:"adapters,omitempty"`
Audit *RosterAudit `json:"audit,omitempty"`
// GitHub, Slack and Google say where those modules are when they are not
// in the controller's process.
GitHub *ModuleRoute `json:"github,omitempty"`
Slack *ModuleRoute `json:"slack,omitempty"`
Google *ModuleRoute `json:"google,omitempty"`
// Secrets says how the secrets the module reads are delivered, for a
// module that runs as a function of its own (the one service document's
// `secrets` is what a controller inside it uses).
Secrets *Secrets `json:"secrets,omitempty"`
// Probes is where /healthz and /readyz answer.
Probes *Address `json:"probes,omitempty"`
// contains filtered or unexported fields
}
Roster is what the two controllers share.
func (*Roster) Converted ¶ added in v1.62.0
Converted reports whether the document was v1, converted as it was loaded.
func (*Roster) Targets ¶ added in v1.76.0
func (r *Roster) Targets() map[string]ModuleRemote
Targets is the routing a controller document says.
func (*Roster) ValidateRoutes ¶ added in v1.76.0
ValidateRoutes is Sluis.ValidateRoutes for a controller document.
type RosterAudit ¶
type RosterAudit struct {
Writer string `json:"writer,omitempty"`
TokenFile string `json:"tokenFile,omitempty"`
}
RosterAudit is the audit installation a controller records to.
type RosterConsole ¶ added in v1.59.0
type RosterConsole struct {
Auth *RosterConsoleAuth `json:"auth,omitempty"`
}
RosterConsole is how a controller authenticates to the console.
type RosterConsoleAWS ¶ added in v1.59.0
type RosterConsoleAWS struct {
// Audience is the one the issuer's AWS federation file names.
Audience string `json:"audience"`
}
RosterConsoleAWS is the AWS proof.
type RosterConsoleAuth ¶ added in v1.59.0
type RosterConsoleAuth struct {
AWS *RosterConsoleAWS `json:"aws,omitempty"`
}
RosterConsoleAuth chooses the proof; `aws` is the function role's web identity token.
type SecretLocation ¶ added in v1.62.0
SecretLocation is where a converted v1 document said one secret was: a variable or a file.
type Secrets ¶ added in v1.62.0
type Secrets struct {
Source string `json:"source"`
Root string `json:"root,omitempty"`
Region string `json:"region,omitempty"`
Endpoint string `json:"endpoint,omitempty"`
Refresh *Duration `json:"refresh,omitempty"`
// KMSKeyID is `ssm`'s customer-managed key for the parameters the
// service writes (credentials, exports). Unset is the AWS-managed key.
KMSKeyID string `json:"kmsKeyId,omitempty"`
// Layout is the storage layout of an `ssm` installation: `v4` (ADR
// 0041), the default, or `v5` (ADR 0072), module first.
Layout string `json:"layout,omitempty"`
// Grace is how long a rotated client secret's previous value is still
// accepted (default 24h). It is the overlap of a
// rotation: the previous revision of the document, while the current
// one is younger than this.
Grace *Duration `json:"grace,omitempty"`
// ReadCache is how long one process keeps a decrypted document it read
// from the `ssm` store (default 5m; 0s turns the cache off). A write
// through the process drops the copy at once; a document that carries
// its own expiry is not kept past it. SLUIS_SECRETS_READ_CACHE_TTL
// overrides it.
ReadCache *Duration `json:"readCache,omitempty"`
}
Secrets is how the secrets a document names are delivered: `env` (SLUIS_SECRET_<NAME>), `file` (<root>/<name>, read on every use) or `ssm` (<root>/internal/config/<name>, read at once and again after `refresh`). See internal/secrets.
type Serve ¶
type Serve struct {
// APIVersion is the document's version: v2. A document without one is v1,
// which [Load] converts.
APIVersion string `json:"apiVersion"`
IssuerURL string `json:"issuerURL"`
Release string `json:"release,omitempty"`
Cluster string `json:"cluster,omitempty"`
AllowInsecure bool `json:"allowInsecure,omitempty"`
Demo bool `json:"demo,omitempty"`
InCluster bool `json:"inCluster,omitempty"`
// Instance names this installation in the default encryption context of
// `keys` ({instance, purpose}). Unset is `release`.
Instance string `json:"instance,omitempty"`
// Keys says which key serves which purpose (`keys.sign` wraps the signing
// key ring). Unset leaves every purpose to its older setting.
Keys *keys.Config `json:"keys,omitempty"`
Listen *Address `json:"listen,omitempty"`
Probes *Address `json:"probes,omitempty"`
Log *Log `json:"log,omitempty"`
Store string `json:"store,omitempty"`
Ports *Ports `json:"ports,omitempty"`
// Platform, Preset and Adapters choose the adapters by name, per concern.
// Absent, the `ports` keys decide, exactly as before they existed.
Platform *Platform `json:"platform,omitempty"`
Preset string `json:"preset,omitempty"`
// Adapters maps a concern (state, secrets, blobs, signing, trigger,
// schedule, audit) to the adapter that replaces the preset's.
Adapters map[string]AdapterChoice `json:"adapters,omitempty"`
// Policy names the policy document. Unset is the built-in two groups, or
// the demonstration policy under `demo`.
Policy *PolicyRef `json:"policy,omitempty"`
PublicURL string `json:"publicURL,omitempty"`
PublicRootURL string `json:"publicRootURL,omitempty"`
SecureCookies *bool `json:"secureCookies,omitempty"`
GroupsScoping string `json:"groupsScoping,omitempty"`
// Secrets says how the secrets this document names are delivered.
Secrets *Secrets `json:"secrets,omitempty"`
Lifetimes *Lifetimes `json:"lifetimes,omitempty"`
Freshness *Freshness `json:"freshness,omitempty"`
Directory *Directory `json:"directory,omitempty"`
Exchange *Exchange `json:"exchange,omitempty"`
Recovery *Recovery `json:"recovery,omitempty"`
Login *Login `json:"login,omitempty"`
Console *Console `json:"console,omitempty"`
OAuthClient *OAuthClient `json:"oauthClient,omitempty"`
SigningKey *SigningKey `json:"signingKey,omitempty"`
Valkey *Valkey `json:"valkey,omitempty"`
Audit *Audit `json:"audit,omitempty"`
// Cloudflare is sluis as the STS for Cloudflare API tokens and R2
// credentials: the accounts it mints in and the presets it mints.
Cloudflare *Cloudflare `json:"cloudflare,omitempty"`
// contains filtered or unexported fields
}
Serve is the configuration of `sluis serve`: the issuer, the console and the directory hub, which run as one process.
func (*Serve) Converted ¶ added in v1.62.0
Converted reports whether the document was v1, converted as it was loaded.
func (*Serve) LegacySecrets ¶ added in v1.62.0
func (s *Serve) LegacySecrets() (map[string]SecretLocation, string)
LegacySecrets is, for a document converted from v1, where v1 said each secret it names was (by the name v2 gives it), and v1's clientSecretsDir. Both are empty for a v2 document.
func (*Serve) Targets ¶ added in v1.76.0
func (s *Serve) Targets() map[string]ModuleRemote
Targets is the routing a v2 `serve` document says: `cloudflare.remote` alone, since the per-module sections came with v3.
func (*Serve) ValidateCloudflare ¶ added in v1.74.0
ValidateCloudflare holds the cloudflare section, and what else in the service document names one of its presets (ports.blob.s3.credentials), to the checks a schema cannot make. A document that never mentions Cloudflare passes: the static credentials of `ports.blob.s3.credentialsRef` need no section.
type Service ¶ added in v1.62.0
type Service interface {
Sluis | Serve | ControllerGitHub | ControllerSlack
}
Service is a service document: what a process is started with.
type SigningKey ¶
type SigningKey struct {
File string `json:"file,omitempty"`
AdditionalFiles []string `json:"additionalFiles,omitempty"`
PollInterval *Duration `json:"pollInterval,omitempty"`
ActivationDelay *Duration `json:"activationDelay,omitempty"`
Overlap *Duration `json:"overlap,omitempty"`
// KMS signs with AWS KMS keys instead of a file. Exclusive with File.
KMS *SigningKeyKMS `json:"kms,omitempty"`
// KMSWrapped signs with key pairs KMS generates and wraps under one
// symmetric key, rotated automatically. Exclusive with File and KMS.
KMSWrapped *SigningKeyKMSWrapped `json:"kmsWrapped,omitempty"`
// VerifyOnly are public keys published in the JWKS and never signed
// with, for a bounded overlap (a cutover from file keys to KMS ones).
VerifyOnly []SigningKeyVerifyOnly `json:"verifyOnly,omitempty"`
}
SigningKey is where the issuer's keys are and how they rotate.
type SigningKeyKMS ¶ added in v1.58.0
type SigningKeyKMS struct {
Keys []string `json:"keys,omitempty"`
Region string `json:"region,omitempty"`
StateSecret string `json:"stateSecret,omitempty"`
// Additional is every OTHER algorithm signed at once, each on its own
// ordered key list, beside Keys (ES384).
Additional []SigningKeyKMSAlg `json:"additional,omitempty"`
}
SigningKeyKMS is the AWS KMS source of the primary signing key.
type SigningKeyKMSAlg ¶ added in v1.58.0
SigningKeyKMSAlg is one more algorithm's KMS keys.
type SigningKeyKMSWrapped ¶ added in v1.61.0
type SigningKeyKMSWrapped struct {
// KeyID is DEPRECATED: the symmetric application key. `keys.sign`
// replaces it; an alias given here is mapped onto `keys.sign` with a
// warning for one release.
KeyID string `json:"keyId,omitempty"`
Region string `json:"region,omitempty"`
// StateSecret names the sign-in state's secret, as for `kms`.
StateSecret string `json:"stateSecret,omitempty"`
// Algorithms are ES384 and/or RS256, the first the default. Unset is
// ES384 and RS256.
Algorithms []string `json:"algorithms,omitempty"`
// RotateEvery is how often a new key pair is generated. Default 24h.
RotateEvery *Duration `json:"rotateEvery,omitempty"`
// Prepublish is how long a new key is published before it signs.
// Default `signingKey.activationDelay` (15m).
Prepublish *Duration `json:"prepublish,omitempty"`
// Retain is how long a superseded key stays published. Default
// `signingKey.overlap`, which is `lifetimes.token` plus a skew margin.
Retain *Duration `json:"retain,omitempty"`
}
SigningKeyKMSWrapped is the `kms-wrapped` signing adapter's settings: one symmetric KMS key, the algorithms signed with, and the rotation schedule.
type SigningKeyVerifyOnly ¶ added in v1.64.0
type SigningKeyVerifyOnly struct {
// File is a PEM public key (or a certificate's) or a JWK. A private key
// is refused at start.
File string `json:"file"`
// KeyID is the `kid` the old tokens carry. Unset is the RFC 7638
// thumbprint, which is what a file signer derived for the key.
KeyID string `json:"kid,omitempty"`
// Alg is the key's algorithm. Unset follows the key.
Alg string `json:"alg,omitempty"`
// Until is an RFC 3339 instant after which the key is not published.
Until string `json:"until,omitempty"`
}
SigningKeyVerifyOnly is one public key published and never signed with.
type SlackController ¶ added in v1.63.0
type SlackController struct {
ControllerCommon
CredentialsDir string `json:"credentialsDir,omitempty"`
}
SlackController is `controllers.slack`.
type Sluis ¶ added in v1.63.0
type Sluis struct {
Serve
// GitHub, Slack and Google say where those modules are when they are not in
// this process: `<module>.remote`, shaped as `cloudflare.remote`.
GitHub *ModuleRoute `json:"github,omitempty"`
Slack *ModuleRoute `json:"slack,omitempty"`
Google *ModuleRoute `json:"google,omitempty"`
Controllers *Controllers `json:"controllers,omitempty"`
}
Sluis is the one service document: the process that serves the issuer, the console and the directory hub and, beside them, runs the controllers it names. Every key of Serve is a key of it, at the top level, and `controllers` is what it adds. apiVersion is v3 (`sluis.truvity.github.io/ sluis/v3`); a v2 `serve` document, or a v1 one, loads as a Sluis with no controllers.
A controller shares what the process already says: the release, the policy, the storage ports and adapters, the audit installation, the log level and the probes. Its own section holds what is its own, and a section that is absent is a controller that is off.
func (*Sluis) GitHubController ¶ added in v1.63.0
func (s *Sluis) GitHubController() *ControllerGitHub
GitHubController is the split GitHub controller's document that this one says, or nil when `controllers.github` is absent. The controller's assembly reads it as it reads the document of `sluis controller github`.
func (*Sluis) SlackController ¶ added in v1.63.0
func (s *Sluis) SlackController() *ControllerSlack
SlackController is Sluis.GitHubController for Slack.
func (*Sluis) Targets ¶ added in v1.76.0
func (s *Sluis) Targets() map[string]ModuleRemote
Targets are the modules this process reaches elsewhere, by name: `cloudflare.remote` and the `remote` of `github`, `slack` and `google`.
func (*Sluis) ValidateRoutes ¶ added in v1.76.0
ValidateRoutes holds `github.remote`, `slack.remote` and `google.remote` to what the schema cannot say.
type SluisBackup ¶ added in v1.75.0
type SluisBackup struct {
APIVersion string `json:"apiVersion"`
// Instance names the installation: the path of its backups in the archive
// bucket and the default encryption context of the archive key.
Instance string `json:"instance,omitempty"`
Log *Log `json:"log,omitempty"`
// Keys is the key service block every product shares. Since format 2 the
// backup module uses none of it: `keys.archive` is accepted for one release
// and ignored (deprecated).
Keys *keys.Config `json:"keys,omitempty"`
Secrets *Secrets `json:"secrets,omitempty"`
Ports *Ports `json:"ports,omitempty"`
Platform *Platform `json:"platform,omitempty"`
Preset string `json:"preset,omitempty"`
Adapters map[string]AdapterChoice `json:"adapters,omitempty"`
Audit *Audit `json:"audit,omitempty"`
Backup Backup `json:"backup"`
}
SluisBackup is the backup module's service document (apiVersion sluis.truvity.github.io/sluis-backup/v1, schemas/config/sluis-backup.schema.json). It holds what the module reads and nothing of the issuer, the console or a policy: the storage it reads an installation from (`ports`, `secrets`), the audit trail, the age recipients a backup is encrypted to, and the bucket it is written to.
func LoadBackup ¶ added in v1.75.0
func LoadBackup(file string) (*SluisBackup, error)
LoadBackup reads the backup module's document, holds it to its schema and to SluisBackup.Validate.
func (*SluisBackup) Deprecated ¶ added in v1.76.1
func (s *SluisBackup) Deprecated() []string
Deprecated reports the keys the document sets that format 2 ignores (backup.key, backup.region, keys.archive), for a warning at start.
func (*SluisBackup) IdentityRef ¶ added in v1.76.1
func (s *SluisBackup) IdentityRef() string
IdentityRef is the name of the restore identity's secret.
func (*SluisBackup) Name ¶ added in v1.75.0
func (s *SluisBackup) Name() string
Name is the installation's name: `instance`, else "sluis".
func (*SluisBackup) RoleOf ¶ added in v1.75.0
func (s *SluisBackup) RoleOf() string
RoleOf is the role the document is deployed as: `backup.role`, else backup.
func (*SluisBackup) Serve ¶ added in v1.75.0
func (s *SluisBackup) Serve() *Serve
Serve is the part of the document the storage ports and the audit trail are opened from, in the shape the shared builders (internal/store, internal/audit) read.
func (*SluisBackup) Validate ¶ added in v1.75.0
func (s *SluisBackup) Validate() error
Validate refuses what the schema cannot say.
type SluisGoogle ¶ added in v1.76.0
type SluisGoogle struct {
APIVersion string `json:"apiVersion"`
// Instance names the installation, as in every module's document.
Instance string `json:"instance,omitempty"`
Log *Log `json:"log,omitempty"`
Probes *Address `json:"probes,omitempty"`
Secrets *Secrets `json:"secrets,omitempty"`
// Audit is the audit installation the module records to: the connections
// it makes and the changes it makes to them, as its own workload. Unset
// only logs what it did.
Audit *RosterAudit `json:"audit,omitempty"`
Ports *Ports `json:"ports,omitempty"`
Platform *Platform `json:"platform,omitempty"`
Preset string `json:"preset,omitempty"`
Adapters map[string]AdapterChoice `json:"adapters,omitempty"`
Google Google `json:"google"`
}
SluisGoogle is the Google module's service document (apiVersion sluis.truvity.github.io/sluis-google/v1, schemas/config/sluis-google.schema.json). It holds what the module reads and nothing of the issuer, the console, the signer or a policy: the storage it keeps its workspaces and the snapshots in (`ports`, `secrets`), and the workspaces it reads (`google`).
func LoadGoogle ¶ added in v1.76.0
func LoadGoogle(file string) (*SluisGoogle, error)
LoadGoogle reads the Google module's document, holds it to its schema and to SluisGoogle.Validate.
func (*SluisGoogle) DeclaredSecrets ¶ added in v1.76.0
func (s *SluisGoogle) DeclaredSecrets() []DeclaredSecret
DeclaredSecrets are the secrets the document declares the module reads: the key of every declared workspace and the OAuth client that reopens one connected by consent (its id too, unless the document gives it). Every one is of a kind the Google module owns; the policy's client secrets and the issuer's keys are not named here because the module has no policy and no signer.
func (*SluisGoogle) Name ¶ added in v1.76.0
func (s *SluisGoogle) Name() string
Name is the installation's name: `instance`, else "sluis".
func (*SluisGoogle) Serve ¶ added in v1.76.0
func (s *SluisGoogle) Serve() *Serve
Serve is the part of the document the storage ports are opened from, in the shape the shared builders (internal/store, internal/secrets) read.
func (*SluisGoogle) Validate ¶ added in v1.76.0
func (s *SluisGoogle) Validate() error
Validate refuses what the schema cannot say.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package duration is the time span a configuration document spells as a Go duration string.
|
Package duration is the time span a configuration document spells as a Go duration string. |
|
Command gen writes the configuration schemas into schemas/config/, and embeds them in the chart's values schema.
|
Command gen writes the configuration schemas into schemas/config/, and embeds them in the chart's values schema. |
|
Package schema builds the JSON Schema of each binary's configuration file.
|
Package schema builds the JSON Schema of each binary's configuration file. |