Documentation
¶
Overview ¶
Package wireguard is what a go-authn provider and a WireGuard gateway agree on about people's keys: what a public key is, and the signed list of the keys people have registered, which the gateway turns into peers.
WireGuard authenticates a peer by its static public key and nothing else: there are no certificates, no expiry and no revocation in the protocol. So the question "may this key connect, and whose is it?" has to be answered outside it, and answered again whenever the answer changes. Here the provider (go-authn/bridge) answers it: a person registers the public key of each device with a token, for a lease, and the provider takes the keys back when the person or their institution is disabled. The gateway pulls the answer as a List, signed by the provider, with a Source.
⛔ Only PUBLIC keys pass through here. A private key is generated on the device and never leaves it; nothing in this package has a place for one.
Index ¶
Constants ¶
const ( // ListType is the "typ" of a signed [List]: not "JWT", so that nothing // verifying tokens takes a list for one, nor the reverse. ListType = "wireguard-peers+jwt" // ListPath is where a provider serves the list, under its issuer. ListPath = "/wireguard/peers" // KeyPath is where a person's client registers and removes a key. KeyPath = "/wireguard/key" // ScopeKeys is the scope a person's token needs to register a key. ScopeKeys = "wireguard" // ScopePeers is the scope a gateway's own token needs to read the list. ScopePeers = "wireguard_peers" )
The names a provider and a gateway share.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Key ¶
type Key [32]byte
Key is a WireGuard public key: an X25519 public value, 32 bytes.
func ParseKey ¶
ParseKey reads a public key as wg(8) prints it: standard base64, 44 characters with its padding.
It refuses:
- any other spelling of the same bytes. The decoding is strict, so a key has exactly one text form, and a list or a store keyed on the text cannot hold one key twice under two names;
- a key of low order, the all-zero key among them. Every exchange with one gives the same shared secret whatever the other side's key (RFC 7748 6.1), so it authenticates nobody, and WireGuard itself refuses the handshake. Registered, it would be a peer that cannot connect, holding an address, and a name in the list for nothing.
type List ¶
type List struct {
// Version increases every time a key is taken back. A gateway that has
// seen a version refuses an older one, so an old list -- signed, and
// listing a key since revoked -- cannot be replayed to it.
Version uint64
// IssuedAt is when the provider wrote it, and Expires when it stops
// being an answer: a gateway that cannot fetch a newer one by then has
// no list rather than a stale one.
IssuedAt, Expires time.Time
Peers []Peer
}
List is the keys a gateway may accept, at one moment.
type Peer ¶
type Peer struct {
Key Key
// Subject is the person's "sub" as the client that registered the key
// sees it: the value a gateway also finds in that person's access
// tokens, whether the client's subjects are public or pairwise.
Subject string
// Username is the name the provider calls them, for logs and routing
// rules; Subject is what ties a key to a person.
Username string
// Device is the name the person gave the key, if any.
Device string
// Expires is the end of the key's lease. A gateway removes the peer then,
// list or no list.
Expires time.Time
}
Peer is one key a person registered, as a gateway needs it.
type Source ¶
type Source struct {
// contains filtered or unexported fields
}
A Source fetches a provider's list for one gateway. It is safe for concurrent use; build one at startup and keep it, since it remembers the newest version it has seen.
type SourceConfig ¶
type SourceConfig struct {
// Issuer is the provider, as its tokens name it.
Issuer string
// ClientID and ClientSecret are the gateway's own client at the
// provider: a confidential client the provider lets read the list.
ClientID, ClientSecret string
// Client is the HTTP client, for a proxy, a private CA or a timeout.
Client *http.Client
// Now overrides the clock, for tests.
Now func() time.Time
}
SourceConfig is how a gateway reaches its provider.