Metadata-Version: 2.5
Name: glovebox-hosts
Version: 0.6.0
Summary: The one hostname spelling and host-matching rules every glovebox component applies
Project-URL: Homepage, https://github.com/AlexanderMattTurner/agent-glovebox
Project-URL: Source, https://github.com/AlexanderMattTurner/agent-glovebox
Author: AlexanderMattTurner
License-Expression: Apache-2.0
Keywords: egress,glovebox,hostname,sandbox
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Security
Requires-Python: >=3.9
Requires-Dist: tldextract==5.3.2
Description-Content-Type: text/markdown

# glovebox-hosts

The one answer to "which host is this" that every part of glovebox uses: the egress proxy's verdict service, the launcher, the WebFetch hook, the session driver and the evals.

A host is compared in one spelling: ASCII only, surrounding whitespace removed, lowercased, and an IP literal in its standard form. A name that is not ASCII, or that starts or ends with a dot, is refused with `HostError` rather than folded, so two readers can never disagree about it.

```python
>>> from glovebox_hosts import canonical_host, split_authority, granting_entries
>>> split_authority("[2001:DB8::1]:443")
('2001:db8::1', 443)
>>> granting_entries("API.example.com", ["example.com"])
['example.com']
>>> granting_entries("a.b.example.com", ["example.com"])
[]
```

A grant on a name reaches that host alone, and a `*.S` grant every name below S. A bar (`constraining_entries`) reaches any depth. A grant may not name a `*.` wildcard over a public suffix, or over a name with one below it (`suffix_below`): `grant_name_refusal` says why, reading the Public Suffix List that `tldextract` bundles. A grant on a public suffix itself is allowed, since it reaches that one host. That is the package's one dependency, and it is imported only when a grant name is judged.

`pod_grants` reads a Kata pod's `glovebox.dev/egress-grants` annotation as every node reads it, so an admission webhook can refuse a pod at submission for the same reason the node would refuse it later. It returns the granted hosts at their tiers, the address grants and the port grants, and raises `GrantRefused` with the node's own message for the first entry the node refuses. How wide an address grant may be is each node's own setting, so it is not checked here.

A host with a port, such as `{"host": "git.example.com:22", "rw": true}`, is a port grant. The node relays a raw stream to that port on the name's public addresses, so it needs `"rw": true`. A host without a port keeps its plain host meaning.

```python
>>> from glovebox_hosts import GrantRefused, pod_grants
>>> granted = pod_grants('["httpbin.org", {"host": "git.example.com:22", "rw": true}]')
>>> granted.hosts
{'httpbin.org': 'ro'}
>>> granted.ports
[PortGrant(host='git.example.com', port=22)]
>>> pod_grants('["*.amazonaws.com"]')
Traceback (most recent call last):
...
glovebox_hosts.GrantRefused: glovebox.dev/egress-grants: '*.amazonaws.com' is a wildcard over a name with the public suffix ...
```
