Documentation
¶
Overview ¶
Package exposure answers "which published container ports can the internet reach" and manages comment-tagged DOCKER-USER rules that restrict them. Published ports skip the INPUT chain, so ufw alone says nothing about them.
Index ¶
- Variables
- func BindsOf(ports []PortBinding) []string
- func Explain(f Finding, outsideLabel string) (explanation, recommendation string)
- func ValidCIDR(s string) bool
- type Chain
- type ChainRule
- type Class
- type Container
- type Finding
- type ImageKind
- type Manager
- func (m *Manager) Apply(ctx context.Context, r Restriction) (changed bool, err error)
- func (m *Manager) Normalize(r Restriction) (Restriction, error)
- func (m *Manager) Plan(r Restriction) (Plan, error)
- func (m *Manager) Prefix() string
- func (m *Manager) ReadChain(ctx context.Context) Chain
- func (m *Manager) Remove(ctx context.Context, port int, proto string) error
- func (m *Manager) Sync(ctx context.Context, want []Restriction) SyncResult
- type Owner
- type OwnerKind
- type Plan
- type PortBinding
- type Restriction
- type Runner
- type Severity
- type SyncResult
- type Verdict
Constants ¶
This section is empty.
Variables ¶
var ErrLockout = errors.New("exposure: restriction would lock out a required port")
ErrLockout is wrapped when a restriction would cut off a port the platform or the operator's SSH session needs.
Functions ¶
func BindsOf ¶
func BindsOf(ports []PortBinding) []string
BindsOf collects the distinct bind addresses, wildcard spelled explicitly.
Types ¶
type Chain ¶
type Chain struct {
// Readable is false when the chain could not be read; Reason says why.
Readable bool
Reason string
Rules []ChainRule
}
Chain is the DOCKER-USER chain as read from the host.
func ParseChain ¶
ParseChain parses `iptables -S DOCKER-USER` output.
type ChainRule ¶
type ChainRule struct {
Raw string
Proto string
DPort int
OrigDPort int
Source string
SourceNegated bool
Target string
Comment string
Complex bool
}
ChainRule is one parsed DOCKER-USER rule. Anything the parser does not fully understand sets Complex, so classification never trusts it.
type Container ¶
type Container struct {
ID string
Name string
Image string
Owner Owner
Ports []PortBinding
Running bool
}
Container is one running container's published ports, as the audit reads them.
type Finding ¶
type Finding struct {
Container string `json:"container"`
Image string `json:"image"`
Owner Owner `json:"owner"`
ImageKind ImageKind `json:"image_kind"`
Protocol string `json:"protocol"`
HostPort int `json:"host_port"`
ContainerPort int `json:"container_port"`
Binds []string `json:"binds"`
Class Class `json:"class"`
Severity Severity `json:"severity"`
// AllowedSources lists the sources a matching rule lets through, when Class is restricted.
AllowedSources []string `json:"allowed_sources,omitempty"`
// Rules are the matching DOCKER-USER rules, verbatim.
Rules []string `json:"rules,omitempty"`
// Managed is true when the matching rule is one this platform created.
Managed bool `json:"managed"`
Explanation string `json:"explanation"`
Recommendation string `json:"recommendation,omitempty"`
// CanRestrict is false when this audit cannot offer the guided fix, with the reason.
CanRestrict bool `json:"can_restrict"`
CannotRestrictWhy string `json:"cannot_restrict_reason,omitempty"`
}
Finding is the audit result for one published port of one container.
func Audit ¶
Audit turns a container list into findings, one per published (port, protocol, container) and sorted worst first.
func (Finding) NeedsAttention ¶
NeedsAttention reports whether the finding is worth surfacing: published beyond the host's private interfaces and not provably restricted.
type ImageKind ¶
type ImageKind string
ImageKind is a coarse guess at what a container runs, from its image name and published port.
const ( KindDatastore ImageKind = "datastore" KindSearch ImageKind = "search" KindAdmin ImageKind = "admin" KindDockerAPI ImageKind = "docker_api" KindWeb ImageKind = "web" KindOther ImageKind = "other" )
Image kinds.
func ImageKindOf ¶
ImageKindOf guesses what a container runs from its image repository name, falling back to the container port.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager reads and edits the DOCKER-USER chain, touching only rules that carry its own comment tag.
func NewFakeManager ¶
func NewFakeManager(prefix string, protected []int, run Runner, lookPath func(string) (string, error), goos string) *Manager
NewFakeManager builds a Manager over fake seams for tests.
func NewManager ¶
NewManager builds a Manager over the real iptables binary. protected lists ports that must never be restricted (control plane, ingress, SSH).
func (*Manager) Apply ¶
Apply installs the restriction idempotently and reports whether anything changed.
func (*Manager) Normalize ¶
func (m *Manager) Normalize(r Restriction) (Restriction, error)
Normalize validates a restriction and returns it in canonical form.
func (*Manager) Plan ¶
func (m *Manager) Plan(r Restriction) (Plan, error)
Plan renders the exact commands Apply would run, in execution order.
func (*Manager) Sync ¶
func (m *Manager) Sync(ctx context.Context, want []Restriction) SyncResult
Sync converges the chain to want: it applies every restriction and removes tagged rules whose restriction no longer exists.
type Owner ¶
type Owner struct {
Kind OwnerKind `json:"kind"`
Name string `json:"name,omitempty"`
// Intentional is true when the operator explicitly asked for public
// access (a database's PubliclyAccessible, an app's public bind).
Intentional bool `json:"intentional,omitempty"`
}
Owner is the platform resource behind a container, if any.
type Plan ¶
type Plan struct {
Commands []string `json:"commands"`
Drops string `json:"drops"`
Tag string `json:"tag"`
// Persistence says plainly how long the rules last.
Persistence string `json:"persistence"`
}
Plan is the exact rule set a restriction produces.
type PortBinding ¶
PortBinding is one published port as Docker reports it.
type Restriction ¶
type Restriction struct {
Port int `json:"port"`
Protocol string `json:"protocol"`
Allow []string `json:"allow"`
}
Restriction is a desired allow-list for one published port.
type Severity ¶
type Severity string
Severity ranks a finding for the operator.
type SyncResult ¶
SyncResult counts what one Sync pass changed.