A machine's filtering is computed from what it was assigned
A rule nobody derives is a rule somebody keeps in step by hand, and five HAL manifests carry a `scope:` key that reads as a restriction and restricts nothing. Both halves are closed here. Manifests are parsed strictly. An unknown key is refused, which is the discipline the host's declaration parser has always had; `scope:` survived because nothing rejected it. A module says what it listens on and who may reach it, and saying from where is required — a rule with no source is open, and must say so rather than appear to restrict something. The mesh gathers every assigned module's ports, widens where two overlap, names every module that wanted each one, and renders one nftables file per node. What no module declared is closed. Three things it deliberately does not do: it writes no forward policy, because what a machine routes is the container runtime's business and dropping there stops every container on the node; it never flushes the whole ruleset, only its own table; and it carries no command to load itself, because the link may not carry an action. A service declares `restart-on` the file instead, which is the shape that rule leaves. Also fixes a fault the lab found: certificateFor asked where every node is without the catalogue, so nothing resolved, every machine looked like it was on no private network, and every certificate the mesh was asked for was refused with a reason that was not true. Asking that question without the catalogue is now refused rather than answered wrongly.
This commit is contained in:
@@ -1211,6 +1211,14 @@ func theRestOfTheMesh(ctx context.Context, inv *inventory.Inventory,
|
||||
func whereEveryoneIs(ctx context.Context, inv *inventory.Inventory,
|
||||
shelf map[string]catalogue.Manifest) (map[string]string, error) {
|
||||
|
||||
if shelf == nil {
|
||||
// Refused rather than answered. Being on the private network is a conclusion about what a
|
||||
// node resolves to, so with no catalogue nothing resolves and the honest answer is
|
||||
// "nobody" — which is wrong, indistinguishable from a mesh with no overlay, and refused
|
||||
// every certificate the mesh was asked for while saying the machine was on no network.
|
||||
return nil, errors.New(
|
||||
"asked where everyone is without the catalogue, which cannot be answered")
|
||||
}
|
||||
places, err := inv.Overlays(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1296,9 +1304,39 @@ func declarationWith(ctx context.Context, inv *inventory.Inventory, node string,
|
||||
break
|
||||
}
|
||||
|
||||
// And who else is on the private network, which is what a rule saying "from the mesh"
|
||||
// resolves to. Every node's address, including this one's: a machine reaching itself by its
|
||||
// own overlay address rather than by loopback is ordinary, and leaving it out would filter
|
||||
// the node's own traffic to itself with no rule naming why.
|
||||
private, err := onThePrivateNetwork(ctx, inv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return plan.Declaration(catalogue.Rendering{
|
||||
Settings: settings, Generators: gens, Grants: grants, Needed: needed,
|
||||
Certificate: certificate, Authority: authority})
|
||||
Certificate: certificate, Authority: authority, Mesh: private})
|
||||
}
|
||||
|
||||
// onThePrivateNetwork is every node's address on the overlay, sorted.
|
||||
//
|
||||
// A node with no address is left out rather than rendered as an empty source: an empty entry in a
|
||||
// source set is a syntax error in the rule file, and a rule file that does not load leaves the
|
||||
// node filtering whatever it was filtering before -- the one outcome worse than a wrong rule,
|
||||
// because nothing reports it.
|
||||
func onThePrivateNetwork(ctx context.Context, inv *inventory.Inventory) ([]string, error) {
|
||||
places, err := inv.Overlays(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var out []string
|
||||
for _, p := range places {
|
||||
if strings.TrimSpace(p.Address) != "" {
|
||||
out = append(out, p.Address)
|
||||
}
|
||||
}
|
||||
sort.Strings(out)
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// certificateFor is what the mesh certifies about one machine's internal name.
|
||||
@@ -1332,7 +1370,16 @@ func certificateFor(ctx context.Context, inv *inventory.Inventory, node string)
|
||||
|
||||
// The name it is certified for. Only a machine on the private network has one — a certificate
|
||||
// for a name nothing resolves is a certificate nothing can check.
|
||||
where, err := whereEveryoneIs(ctx, inv, nil)
|
||||
//
|
||||
// With the catalogue, not without it. Being on the private network is a conclusion about what
|
||||
// a node resolves to, so a nil shelf resolves nothing and every machine looks like it is on no
|
||||
// network — which refused every certificate the mesh was asked for, and said the machine was
|
||||
// not on a network it plainly was.
|
||||
shelf, err := inv.Catalogue(ctx)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
where, err := whereEveryoneIs(ctx, inv, shelf)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user