Documentation
¶
Overview ¶
Package policy is lockhttp's policy: the profile the human writes in the console account's config file, in canonical form. The console approves it (lockkit's "the AI tightens, the human loosens" review) and serves it to the gate; the gate never reads a policy file.
Index ¶
- Constants
- Variables
- func CheckHostPattern(key, h string, single bool) (string, error)
- func DefaultConfig(name string, production bool, extra []string) string
- func DefaultProfile(name string, production bool, extra []string) string
- func FormatSize(n int64) string
- func HostMatch(pat, host string) bool
- func ImportHosts(imports []string) ([]string, error)
- func IsMessaging(host string) bool
- func IsPublish(host string) bool
- func IsReceivePack(path, rawQuery string) bool
- func ParseSize(s string) (int64, error)
- func Profiles(data []byte, name string) ([]string, error)
- func PublishMethods(host string, methods []string) bool
- func UnderAnthropic(host string) bool
- type InternalHost
- type Policy
- func (p Policy) AutoForbidden(r Rule) string
- func (p Policy) CDNFor(origin, target string) bool
- func (p Policy) Clone() Policy
- func (p Policy) Denied(host string) bool
- func (p Policy) Describe() []string
- func (p Policy) Diff(approved kconfig.Policy) []kconfig.Change
- func (p Policy) Fingerprint() string
- func (p Policy) InternalHost(host string) (InternalHost, bool)
- func (p Policy) Profile() console.Profile
- func (p Policy) Spliced(host string) bool
- func (p Policy) Trusts(host string) bool
- type Rule
Constants ¶
const ( // ModeEnforce applies every verdict. ModeEnforce = "enforce" // ModeShadow logs what would have asked or been denied and lets it // pass; the floor and secret matches stay enforced. ModeShadow = "shadow" // ModeOff (heuristics only) computes no score. ModeOff = "off" )
Modes of the policy and of the heuristics.
const ( VerdictDeny = "deny" VerdictAsk = "ask" // VerdictAuto asks without NeverAuto: auto mode may answer it. VerdictAuto = "auto" VerdictFree = "free" )
Verdicts of a rule.
const ( DefaultBufferLimit = 10 << 20 DefaultHold = 60 DefaultConnectGrant = 600 DefaultIdle = 24 * 3600 DefaultMaxSession = 24 * 3600 )
Defaults (decisions D5 and the connect grant).
const ConfigHeader = `` /* 196-byte string literal not displayed */
ConfigHeader opens the config file `lockhttp profile add` creates.
Variables ¶
var AnthropicDomains = []string{"anthropic.com", "claude.ai", "claude.com"}
AnthropicDomains are the domains whose other hosts always ask (NeverAuto) unless a rule says otherwise.
var ClaudeHosts = []string{"api.anthropic.com", "claude.ai", "console.anthropic.com", "statsig.anthropic.com"}
ClaudeHosts are free at the domain in phase 1 (CONNECT): the hosts Claude Code reaches. Any other host under the Anthropic domains asks.
var DefaultRedirectCDN = []string{
"ghcr.io>pkg-containers.githubusercontent.com",
"github.com>objects.githubusercontent.com",
"github.com>release-assets.githubusercontent.com",
"github.com>codeload.github.com",
"api.github.com>codeload.github.com",
"registry-1.docker.io>production.cloudflare.docker.com",
"proxy.golang.org>storage.googleapis.com",
"pypi.org>files.pythonhosted.org",
}
DefaultRedirectCDN are the CDNs an origin's 3xx may send a GET to (the exact target, once, within 60 s), whatever the policy adds.
var DocsTrusted = []string{
"go.dev", "pkg.go.dev", "proxy.golang.org", "sum.golang.org", "storage.googleapis.com",
"docs.python.org", "pypi.org", "files.pythonhosted.org",
"registry.npmjs.org", "nodejs.org",
"developer.mozilla.org", "docs.docker.com", "kubernetes.io", "man7.org", "docs.anthropic.com",
"github.com", "api.github.com", "codeload.github.com", "objects.githubusercontent.com",
"raw.githubusercontent.com", "release-assets.githubusercontent.com",
"crates.io", "static.crates.io", "index.crates.io",
"deb.debian.org", "security.debian.org", "archive.ubuntu.com", "security.ubuntu.com",
"dl-cdn.alpinelinux.org",
}
DocsTrusted is the initial trusted read set (decision D8).
var MessagingHosts = []string{
"hooks.slack.com", "slack.com", "*.slack.com",
"gmail.googleapis.com", "graph.microsoft.com", "outlook.office.com", "outlook.office365.com",
"discord.com", "discordapp.com", "api.telegram.org", "api.twilio.com",
"api.sendgrid.com", "api.mailgun.net", "api.postmarkapp.com", "smtp.gmail.com",
"api.pushover.net", "ntfy.sh", "webhook.site", "*.webhook.office.com",
}
MessagingHosts send messages on someone's behalf: every write asks, and no rule may make them auto.
var PublishHosts = []string{
"registry.npmjs.org", "upload.pypi.org", "test.pypi.org", "crates.io", "rubygems.org",
"registry-1.docker.io", "ghcr.io", "quay.io", "*.pkg.dev", "*.azurecr.io",
"api.nuget.org", "repo.maven.apache.org", "uploads.github.com",
}
PublishHosts are package and image registries: a write there publishes.
Functions ¶
func CheckHostPattern ¶
CheckHostPattern validates and normalises a host or "*.domain" pattern. A single-label host is accepted only when single is set (internal hosts); IP literals never are.
func DefaultConfig ¶
DefaultConfig is a new config file: ConfigHeader and DefaultProfile.
func DefaultProfile ¶ added in v0.7.0
DefaultProfile is the profile `lockhttp profile add` writes: the docs set, plus extra (checked entries, from ImportHosts) as trusted reads. name is a valid profile name (config.CheckProfileName).
func HostMatch ¶
HostMatch matches a host against a pattern: an exact host, "*.domain" (any subdomain, not the domain itself) or "*" (any host).
func ImportHosts ¶ added in v0.7.0
ImportHosts reads hosts to trust for reads in the format of lea's LEA_EGRESS_ALLOW: "example.org" trusts that host, ".corp.example" the domain and its subdomains. It returns the trusted entries they make, checked and normalised. Its error names the entry's position, never the entry (it may be anything pasted in the wrong place).
func IsMessaging ¶
IsMessaging reports whether host sends messages.
func IsReceivePack ¶
IsReceivePack reports whether path pushes to a git repository.
func PublishMethods ¶
PublishMethods reports whether methods (empty: all) include one that publishes on registry host: PUT, PATCH, DELETE anywhere, and any write on an upload host.
func UnderAnthropic ¶
UnderAnthropic reports whether host is one of the Anthropic domains or a subdomain of one.
Types ¶
type InternalHost ¶
type InternalHost struct {
Host string `json:"host"`
Ports []int `json:"ports"`
// Read makes reads free; otherwise every request asks.
Read bool `json:"read"`
}
InternalHost is a host of the user's internal-hosts list: it may resolve to a private address, on the ports it declares.
type Policy ¶
type Policy struct {
Name string `json:"name"`
Production bool `json:"production"`
Mode string `json:"mode"`
Heuristics string `json:"heuristics"`
// BufferLimit is the largest body the gate holds for a human (bytes).
BufferLimit int64 `json:"buffer_limit"`
// Hold is how long the gate holds a request for the human (seconds).
Hold int64 `json:"hold"`
// ConnectGrant is how long an approved CONNECT opens its host for the
// container (seconds).
ConnectGrant int64 `json:"connect_grant"`
IdleTimeout int64 `json:"idle_timeout"`
MaxSession int64 `json:"max_session"`
// Trusted hosts are free for reads (GET, HEAD, OPTIONS without body).
Trusted []string `json:"trusted"`
// Splice hosts are never decrypted: decided at the domain.
Splice []string `json:"splice"`
// Deny hosts are always refused.
Deny []string `json:"deny"`
// RedirectCDN lists "origin>cdn": a 3xx from origin to cdn lets the
// same container GET the exact target once, within 60 s.
RedirectCDN []string `json:"redirect_cdn"`
Internal []InternalHost `json:"internal_hosts"`
Rules []Rule `json:"rules"`
}
Policy is one profile in canonical form: sorted lists, defaults applied, durations in seconds. Its JSON is what the console fingerprints and stores as the approved policy, and what the gate receives.
func Parse ¶
Parse decodes the config file data and returns profile in canonical form. Any unknown key, any key that looks like a secret, and any rule that would let auto mode answer a forbidden class is refused.
func (Policy) AutoForbidden ¶
AutoForbidden returns why rule may not have verdict auto in p, or "". The classes are those that always need a human: production, all hosts, a spliced host, messaging, registry publishing, git-receive-pack. The runtime classes (an exfiltration score, a secret, an upload) are checked per request.
func (Policy) Diff ¶
Diff implements config.Policy: what changed since approved, each change marked Loosens when it widens what passes without a human.
func (Policy) Fingerprint ¶
Fingerprint is the canonical hash of p, as the console stores it.
func (Policy) InternalHost ¶
func (p Policy) InternalHost(host string) (InternalHost, bool)
InternalHost returns the internal host entry of host.
type Rule ¶
type Rule struct {
ID string `json:"id"`
Container string `json:"container,omitempty"`
Host string `json:"host"`
Methods []string `json:"methods"`
// Path is an exact path, or a prefix when it ends with "*"; "" is any.
Path string `json:"path,omitempty"`
Verdict string `json:"verdict"`
// MaxBody bounds the body of a matching request (bytes, 0 = the
// buffer limit).
MaxBody int64 `json:"max_body,omitempty"`
// Expires is the last day (UTC) the rule applies, "" for never.
Expires string `json:"expires,omitempty"`
Note string `json:"note,omitempty"`
}
Rule is one policy rule. It applies to every container or to one, never to an agent: an agent name is declarative.
func (Rule) MatchesMethod ¶
MatchesMethod reports whether method is covered by r.Methods (empty: every method).
func (Rule) MatchesPath ¶
MatchesPath reports whether path is covered by r.Path.