config

package
v1.74.2 Latest Latest
Warning

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

Go to latest
Published: Oct 9, 2026 License: MIT Imports: 20 Imported by: 1

Documentation

Overview

Package config is sluis's configuration as a public, stable surface: the documents a process is started with, how to load and check them, and the installation document an estate writes once and renders them from.

An estate knows one thing about an installation (where it runs, which AWS resources and which OpenBao it is built on, whom it trusts, what its clients are) and sluis needs two documents of it: the service document (`sluis.yaml`, apiVersion sluis.truvity.github.io/sluis/v3) and the policy document (`policy.yaml`, .../policy/v2). The installation (apiVersion sluis.truvity.github.io/installation/v1, Installation) is the estate's side of that line and Render is sluis's: the same function `sluisctl render` runs, and the one the Pulumi library (github.com/truvity/sluis/deploy/pulumi) calls, so a Lambda estate and a Kubernetes estate write the documents the same way and neither hand-renders them.

in, err := config.LoadInstallation("installation.yaml")
service, policy, err := config.Render(in)

Render is deterministic (sorted keys, a fixed layout) and holds both outputs to the loader the service runs at start, so a document it returns is one the service accepts. Nothing here reads a secret: a document names each secret and the installation never carries a value.

The documents' own types are the binary's, re-exported: a field of one is reachable by value, and the types are held to their schemas (schemas/config/) by the tests of this repository. A key this package does not name is refused by the schema, never dropped.

Index

Constants

View Source
const (
	// LambdaPolicyFile is the policy in the configuration layer.
	LambdaPolicyFile = "/opt/sluis/policy.yaml"
	// KubernetesPolicyFile is where the chart mounts the policy document.
	KubernetesPolicyFile = "/var/run/access-issuer/policy/policy.yaml"
	// ServerPolicyFile is the policy of a process on a host.
	ServerPolicyFile = "/etc/sluis/policy.yaml"
)

Where each shape finds the policy document, unless the installation says.

View Source
const (
	// StateSecretName is the issuer's sign-in state secret.
	StateSecretName = "issuer/state-secret"
	// RecoveryPasswordName is the recovery password, where there is no cluster
	// to prove access to.
	RecoveryPasswordName = "recovery/password"
)

The names layout v3 gives the secrets sluis itself writes. They are fixed, so an installation never repeats them.

View Source
const DefaultFunctionName = "sluis"

DefaultFunctionName is the Lambda function an installation that names none is rendered for.

View Source
const EnvConfig = internal.EnvConfig

EnvConfig is the variable that names the service document when a process is given no --config.

View Source
const Group = internal.Group

Group is the group of the documents' kinds: an apiVersion is `<Group>/<document>/v<N>`.

View Source
const InstallationVersion = Group + "/installation/v1"

InstallationVersion is the apiVersion of the installation document.

View Source
const LiveAlias = "live"

LiveAlias is the alias of the Lambda function that every caller uses: the API, the schedules and a run-now. The Lambda shape's `invoke` trigger names `<function>:live`, so that a run-now runs the version the schedules run.

Variables

This section is empty.

Functions

func APIVersion

func APIVersion(document string) string

APIVersion is the apiVersion this build writes for one document: `sluis` (v3), `policy` (v2) or `installation` (v1).

func ConsoleAudience

func ConsoleAudience(in *Installation) string

ConsoleAudience is the audience an AWS role's web identity token is minted for to be a bearer at the console: `console.awsAudience`, else the console's URL (the service's own default).

func DefaultSignKeyAlias added in v1.74.0

func DefaultSignKeyAlias(instance string) string

DefaultSignKeyAlias is the alias of an installation's `keys.sign` key when the installation names none: the one the Pulumi library's grants are written for.

func InstallationSchema

func InstallationSchema() []byte

InstallationSchema is the authored schema of the installation document, the file schemas/config/installation.schema.json: the one `sluisctl render` holds a document to, and the one an estate's CI can validate against without this package.

func Load

func Load[T Document](file string) (*T, error)

Load reads one document from a file, holds it to its schema and decodes it. A v2 document is validated as it stands; an older one the binary still reads is converted. For the policy document the semantic checks run too.

func Render

func Render(in *Installation) (service, policy []byte, err error)

Render writes the two documents of an installation: the service document (`sluis.yaml`, sluis/v3) and the policy document (`policy.yaml`, policy/v2).

It is deterministic: the keys of both are sorted, `apiVersion` comes first, and nothing but the installation decides a byte of the output, so a renderer run twice, or by `sluisctl render` and by the Pulumi library, writes the same documents. It does not change in.

Render writes only what the installation says or the shape implies, and says in its error which key is wrong. Both outputs are then loaded by the loader the service runs at start (the schema, then the semantic checks), so a document Render returns is one the service accepts. What only a running process can check, such as an adapter that needs a platform answer the platform does not give, is still checked at start.

What the shape implies:

  • the preset, when none is named;
  • `policy.file`, `publicURL`, `publicRootURL` and `inCluster`;
  • the adapters the AWS resources and the OpenBao settings stand for, for each concern `adapters` does not name;
  • for shape lambda, the library-owned names: `secrets` (ssm, the instance's root), `recovery.passwordSecret`, and the `invoke` trigger's function; and for any signing by KMS, the state secret.

A value the installation writes that disagrees with what the shape fixes is an error, not a choice.

func SSMRoot

func SSMRoot(instance string) string

SSMRoot is the installation's secrets root in layout v3: /sluis/<instance>.

func Validate

func Validate(name string, doc any) error

Validate checks a decoded document against its authored schema: name is `sluis`, `policy` or `installation`. The chart's tests call it on what the chart renders.

func ValidateInstallation

func ValidateInstallation(doc any) error

ValidateInstallation checks a decoded installation document (a generic YAML or JSON value) against the schema.

Types

type AWS

type AWS struct {
	Account string `json:"account,omitempty"`
	Region  string `json:"region,omitempty"`
	// FunctionName is the Lambda function the `invoke` trigger names (through its `live` alias). Unset is
	// `sluis`.
	FunctionName string `json:"functionName,omitempty"`
	// Table is the DynamoDB table of the `dynamodb` state adapter.
	Table string `json:"table,omitempty"`
	// Bucket is the S3 bucket of the `s3` blobs adapter.
	Bucket string `json:"bucket,omitempty"`
	// AuditQueueURL is the SQS queue of the `sqs` audit adapter.
	AuditQueueURL string `json:"auditQueueURL,omitempty"`
}

AWS is the account and the resources an installation is built on. Each resource becomes the setting of the adapter that uses it.

type AWSAccount

type AWSAccount struct {
	Account string   `json:"account"`
	Name    string   `json:"name"`
	Issuer  string   `json:"issuer"`
	JWKSURI string   `json:"jwksUri,omitempty"`
	OrgID   string   `json:"orgId,omitempty"`
	Algs    []string `json:"algs,omitempty"`
}

AWSAccount is one trusted account.

type Access

type Access struct{ policy.Policy }

Access is the access model's tables, as the policy document holds them.

func (Access) MarshalJSON

func (a Access) MarshalJSON() ([]byte, error)

MarshalJSON writes the tables as the access model writes them.

func (*Access) UnmarshalJSON

func (a *Access) UnmarshalJSON(raw []byte) error

UnmarshalJSON reads the tables as the policy document does (JSON is YAML): through the access model's own strict parser.

type AdapterChoice

type AdapterChoice = internal.AdapterChoice

AdapterChoice names the adapter of one concern and its settings.

type AgentLifetimes added in v1.69.0

type AgentLifetimes = internal.AgentLifetimes

AgentLifetimes is `lifetimes.agent`: the agent session class's own.

type Apps

type Apps struct{ internal.PolicyApps }

Apps is what an operator may make on the console: the policy document's `apps`, under the same keys.

func (Apps) MarshalJSON

func (a Apps) MarshalJSON() ([]byte, error)

MarshalJSON writes the section under the keys the policy document gives it.

func (*Apps) UnmarshalJSON

func (a *Apps) UnmarshalJSON(raw []byte) error

UnmarshalJSON reads the section as the policy document does.

type Audit

type Audit = internal.Audit

Audit is `audit`: the audit installation the service records to.

type Cloudflare added in v1.74.0

type Cloudflare struct {
	internal.Cloudflare
	// Grants say which group or CI job may ask for which preset.
	Grants []internal.CloudflareGrant `json:"grants,omitempty"`
}

Cloudflare is the service document's `cloudflare` section and, beside it, the grants the policy document's `cloudflare` holds.

func (*Cloudflare) Declared added in v1.74.0

func (c *Cloudflare) Declared() bool

Declared reports whether the installation declares any preset: the library then schedules the rotation and grants the function what it needs.

type CloudflareAccount added in v1.74.0

type CloudflareAccount = internal.CloudflareAccount

CloudflareAccount is one Cloudflare account and its minter credential's address.

type CloudflareGrant added in v1.74.0

type CloudflareGrant = internal.CloudflareGrant

CloudflareGrant opens presets to a group or a CI job.

type CloudflarePreset added in v1.74.0

type CloudflarePreset = internal.CloudflarePreset

CloudflarePreset is one thing sluis mints.

type CloudflareSection added in v1.74.0

type CloudflareSection = internal.Cloudflare

CloudflareSection is the service document's `cloudflare`: the accounts and presets. Cloudflare adds the policy's grants to it.

type Console

type Console = internal.Console

Console is `console`: where the console is published.

type Controllers

type Controllers struct {
	GitHub *GitHubController `json:"github,omitempty"`
	Slack  *SlackController  `json:"slack,omitempty"`
}

Controllers are the controllers the installation runs. A nil one is off.

type Directory

type Directory = internal.Directory

Directory is `directory`: the corporate directories declared.

type Document

type Document = internal.Document

Document is what Load reads.

type Duration

type Duration = duration.Duration

Duration is a time span as a document spells it: "30s", "2m", "168h".

type Exchange

type Exchange struct {
	Audience string             `json:"audience,omitempty"`
	Clusters []FederatedCluster `json:"clusters,omitempty"`
	AWS      *FederatedAWS      `json:"aws,omitempty"`
	GitHub   *ExchangeGitHub    `json:"github,omitempty"`
}

Exchange is how the token exchange verifies workloads. Audience is the service document's; the rest is the policy document's `exchange`.

type ExchangeGitHub

type ExchangeGitHub struct {
	Owners []string `json:"owners,omitempty"`
}

ExchangeGitHub is whose GitHub Actions tokens are verified.

type FederatedAWS

type FederatedAWS struct {
	Audience string       `json:"audience,omitempty"`
	MaxAge   *Duration    `json:"maxAge,omitempty"`
	Accounts []AWSAccount `json:"accounts,omitempty"`
}

FederatedAWS is the AWS accounts whose roles' outbound identity tokens are verified.

type FederatedCluster

type FederatedCluster struct {
	Name    string `json:"name"`
	Issuer  string `json:"issuer"`
	JWKSURI string `json:"jwksUri,omitempty"`
}

FederatedCluster is one cluster whose ServiceAccount tokens are verified.

type Freshness

type Freshness = internal.Freshness

Freshness is `freshness`: how the directory's snapshot is kept current.

type GitHubController

type GitHubController struct {
	internal.GitHubController
	EnabledOrgs []string `json:"enabledOrgs,omitempty"`
}

GitHubController is the GitHub controller: its own keys go to the service document's `controllers.github`, EnabledOrgs to the policy document's.

type Installation

type Installation struct {
	// APIVersion is [InstallationVersion].
	APIVersion string `json:"apiVersion"`
	// Instance is the installation's name (`acme`, `prod`). Its SSM root is
	// /sluis/<instance>.
	Instance string `json:"instance"`
	// Shape is where it runs.
	Shape Shape `json:"shape"`
	// Preset names the adapters of a whole platform. Unset follows the shape:
	// aws-hybrid (lambda), k8s-aws (kubernetes with `aws`), k8s-openbao
	// (kubernetes with `openbao`), k8s-minimal, server.
	Preset string `json:"preset,omitempty"`
	// Release is the name the installation's objects carry. Unset is `sluis`.
	Release string `json:"release,omitempty"`
	// Cluster names the cluster in a ServiceAccount's subject.
	Cluster string `json:"cluster,omitempty"`
	// PolicyFile is where the service finds the policy document. Unset follows
	// the shape.
	PolicyFile string `json:"policyFile,omitempty"`

	Issuer    Issuer     `json:"issuer"`
	Log       *Log       `json:"log,omitempty"`
	Lifetimes *Lifetimes `json:"lifetimes,omitempty"`
	Freshness *Freshness `json:"freshness,omitempty"`
	// Secrets is the service document's `secrets`, for a platform with no
	// secrets adapter of its own. Shape lambda fills it (ssm, the instance's
	// root) and refuses another value.
	Secrets *Secrets `json:"secrets,omitempty"`

	// AWS is the account and the resources the installation is built on.
	AWS *AWS `json:"aws,omitempty"`
	// OpenBao is the OpenBao the secrets are kept in.
	OpenBao *OpenBao `json:"openbao,omitempty"`
	// Adapters name single concerns over what the preset and the resources
	// above give.
	Adapters map[string]AdapterChoice `json:"adapters,omitempty"`

	// Keys says which key serves which purpose (the service document's
	// `keys`). With `signingKey.kmsWrapped` and no `keys`, the sign key is
	// alias/sluis-<instance>-sign on kms.
	Keys        *keys.Config `json:"keys,omitempty"`
	SigningKey  *SigningKey  `json:"signingKey,omitempty"`
	Recovery    *Recovery    `json:"recovery,omitempty"`
	Login       *Login       `json:"login,omitempty"`
	Console     *Console     `json:"console,omitempty"`
	OAuthClient *OAuthClient `json:"oauthClient,omitempty"`
	Valkey      *Valkey      `json:"valkey,omitempty"`
	Directory   *Directory   `json:"directory,omitempty"`
	Audit       *Audit       `json:"audit,omitempty"`
	// Cloudflare is sluis as the STS for Cloudflare tokens and R2 credentials:
	// the accounts and presets go to the service document's `cloudflare`, the
	// grants to the policy document's.
	Cloudflare *Cloudflare `json:"cloudflare,omitempty"`

	// Exchange is how the token exchange verifies workloads and whom it trusts.
	Exchange *Exchange `json:"exchange,omitempty"`
	// Apps is what an operator may make on the console.
	Apps *Apps `json:"apps,omitempty"`
	// Controllers are the controllers that run, and what each may change.
	Controllers *Controllers `json:"controllers,omitempty"`
	// Access is the access model's tables: groups, clients, resources and the
	// GitHub and Slack bindings.
	Access *Access `json:"access,omitempty"`
}

Installation is everything an estate knows about one installation of sluis. It is a superset of the service document and the policy document: a section is under the key the document gives it (the types are the documents' own), and the installation adds what a document cannot say, which is the shape it runs in and the AWS and OpenBao resources it is built on. Render splits it into the two documents.

It holds no secret. A document names each secret, and where the names are read from is `secrets` or the secrets adapter.

func LoadInstallation

func LoadInstallation(file string) (*Installation, error)

LoadInstallation reads an installation document from a file and holds it to its schema.

func (*Installation) String

func (in *Installation) String() string

String names the installation without printing any of it.

type Issuer

type Issuer struct {
	// URL is the issuer (`issuerURL`).
	URL string `json:"url"`
	// ConsoleURL is `publicURL`. Unset is URL plus /console.
	ConsoleURL string `json:"consoleURL,omitempty"`
	// RootURL is `publicRootURL`. Unset is URL.
	RootURL string `json:"rootURL,omitempty"`
	// SecureCookies is `secureCookies`.
	SecureCookies *bool `json:"secureCookies,omitempty"`
	// GroupsScoping is `groupsScoping`: off, report or enforce.
	GroupsScoping string `json:"groupsScoping,omitempty"`
}

Issuer is the issuer and where a browser reaches the console.

type Lifetimes

type Lifetimes = internal.Lifetimes

Lifetimes is `lifetimes`: how long what the issuer hands out lives.

type Log

type Log = internal.Log

Log is `log`.

type Login

type Login = internal.Login

Login is `login`: how a person signs in to the console.

type OAuthClient

type OAuthClient = internal.OAuthClient

OAuthClient is `oauthClient`: the client registered with the directory backend.

type OpenBao

type OpenBao struct {
	Address   string       `json:"address"`
	CAFile    string       `json:"caFile,omitempty"`
	Mount     string       `json:"mount,omitempty"`
	Namespace string       `json:"namespace,omitempty"`
	Root      string       `json:"root"`
	Auth      OpenBaoLogin `json:"auth"`
}

OpenBao is the OpenBao the secrets are kept in: the settings of the `openbao` secrets adapter.

type OpenBaoLogin

type OpenBaoLogin struct {
	Method    string `json:"method"`
	Mount     string `json:"mount,omitempty"`
	Role      string `json:"role"`
	TokenFile string `json:"tokenFile,omitempty"`
}

OpenBaoLogin is how the service logs in to the OpenBao.

type Policy

type Policy = policy.Policy

Policy is the access model's tables, which a policy document holds.

type PolicyDocument

type PolicyDocument = internal.PolicyDocument

PolicyDocument is the policy document (v2): the access model's tables and whom the exchange trusts, what an operator may make, what each controller may change and what is copied out.

func RenderPolicyLayers

func RenderPolicyLayers(path string) (*PolicyDocument, error)

RenderPolicyLayers builds the one canonical policy document from a file or a directory of layers (a v1 policy file, an access document, or a policy document fragment), merged in name order and held to every check the service runs at start. It is what `sluisctl policy render` runs; an estate that writes an Installation has no layers to merge and calls Render.

type Recovery

type Recovery = internal.Recovery

Recovery is `recovery`: the sign-in that needs no directory.

type Secrets

type Secrets = internal.Secrets

Secrets is `secrets`: how the secrets a document names are delivered.

type Shape

type Shape string

Shape is where an installation runs.

const (
	// ShapeLambda is one AWS Lambda function behind an HTTP API; the documents
	// are an immutable configuration layer mounted at /opt/sluis.
	ShapeLambda Shape = "lambda"
	// ShapeKubernetes is one Deployment; the chart mounts the documents.
	ShapeKubernetes Shape = "kubernetes"
	// ShapeServer is one process on a host.
	ShapeServer Shape = "server"
)

The shapes.

type SigningKey

type SigningKey = internal.SigningKey

SigningKey is `signingKey`: where the issuer's keys are and how they rotate.

type SlackController

type SlackController struct {
	internal.SlackController
	EnabledWorkspaces []string `json:"enabledWorkspaces,omitempty"`
}

SlackController is GitHubController for Slack.

type Sluis

type Sluis = internal.Sluis

Sluis is the one service document (v3): the issuer, the console, the directory hub and, under `controllers`, the controllers the process runs.

type Valkey

type Valkey = internal.Valkey

Valkey is `valkey`: the shared store for logins in progress.

Jump to

Keyboard shortcuts

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