Documentation
¶
Overview ¶
Package dnsserver is an in-process DNS server for tests: an authoritative server with a small zone store, RFC 2136 UPDATE with TSIG, and a log of every message it received. It is imported by tests only; it listens on 127.0.0.1 with random ports, needs no privileges and runs the same on Linux, macOS and Windows.
The Store is what the tests of the agent and of the ACME server share: the agent writes TXT records into it through RFC 2136 (or through the Cloudflare stub of this package), and the ACME server reads them through this server as its resolver.
Index ¶
- Constants
- type CloudflareOptions
- type CloudflareRequest
- type CloudflareStub
- type Key
- type Message
- type Record
- type Server
- type Store
- func (s *Store) AddTXT(name, value string)
- func (s *Store) AddZone(zone string)
- func (s *Store) CNAME(name string) (string, bool)
- func (s *Store) ChallengeRecords() []Record
- func (s *Store) DeleteTXT(name, value string) bool
- func (s *Store) DeleteTXTSet(name string)
- func (s *Store) HasName(name string) bool
- func (s *Store) Serial() uint32
- func (s *Store) SetCNAME(name, target string)
- func (s *Store) TXT(name string) []string
- func (s *Store) ZoneOf(name string) (string, bool)
- func (s *Store) Zones() []string
Constants ¶
const ChallengeLabel = "_acme-challenge."
ChallengeLabel is the first label of every dns-01 record name.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type CloudflareOptions ¶
type CloudflareOptions struct {
// Token is the API token that may edit DNS records.
Token string
// ZoneToken, if set, is the only token that may list zones (the split
// Zone:Read and DNS:Edit setup); otherwise Token does both.
ZoneToken string
}
CloudflareOptions configure the Cloudflare stub.
type CloudflareRequest ¶
type CloudflareRequest struct {
Method, Path, Query string
// Authorization is the header as sent, "Bearer <token>".
Authorization string
}
CloudflareRequest is one request the stub saw.
type CloudflareStub ¶
type CloudflareStub struct {
// URL is the API base, https://127.0.0.1:port/client/v4.
URL string
// Roots trusts the stub's certificate.
Roots *x509.CertPool
// contains filtered or unexported fields
}
CloudflareStub is an httptest TLS server that speaks the part of the Cloudflare v4 API that the agent uses (list zones, create and delete a DNS record) and writes into a Store, so the ACME server's resolver sees what the agent "published".
func StartCloudflare ¶
func StartCloudflare(tb testing.TB, store *Store, opts CloudflareOptions) *CloudflareStub
StartCloudflare starts the stub until the test ends.
func (*CloudflareStub) ErrorText ¶
func (c *CloudflareStub) ErrorText(s string)
ErrorText sets the message of every error answer, to test that a secret in an API answer does not reach a log.
func (*CloudflareStub) FailDeletes ¶
func (c *CloudflareStub) FailDeletes(status int)
FailDeletes makes every DELETE answer with this HTTP status (0 = normal).
func (*CloudflareStub) LoseCreateAnswers ¶
func (c *CloudflareStub) LoseCreateAnswers(body string)
LoseCreateAnswers makes the stub create a record as usual but answer the request with body (HTTP 502, not JSON), as a proxy that loses the real answer would: the record exists, and the client never learns its ID.
func (*CloudflareStub) NotJSON ¶
func (c *CloudflareStub) NotJSON(body string)
NotJSON makes every answer this body with status 200 (a captive portal or a broken proxy). "" = normal.
func (*CloudflareStub) Requests ¶
func (c *CloudflareStub) Requests() []CloudflareRequest
Requests returns the log.
type Key ¶
type Key struct {
// Name is the key name, e.g. "acme-agent".
Name string
// Secret is the base64 secret, as in BIND's key statement.
Secret string
// Algorithm is "hmac-sha256" (default), "hmac-sha384" or "hmac-sha512".
Algorithm string
// Allow limits the names this key may change (BIND's update-policy). Nil
// allows every name in the zone. A refused name makes the whole UPDATE
// REFUSED.
Allow func(name string) bool
}
Key is a TSIG key the server accepts for UPDATE.
type Message ¶
type Message struct {
Network string // "udp" or "tcp"
Opcode string // "QUERY" or "UPDATE"
Name string // the question name, or the zone of an UPDATE
Type string // the question type
Rcode string // the answer's response code
Signed bool // the request carried a TSIG record
TSIGOK bool // ... and it verified
Updates int // records in the update section
}
Message is one request the server received.
type Server ¶
type Server struct {
// Store holds the zones; tests read and write it directly.
Store *Store
// contains filtered or unexported fields
}
Server is the running test server.
func Start ¶
Start runs a server on 127.0.0.1 (the same random port for UDP and TCP) until the test ends. Without keys, UPDATE needs no signature.
func (*Server) ForgeResponseMAC ¶
ForgeResponseMAC makes every signed answer carry a wrong MAC.
func (*Server) HideTXT ¶
HideTXT makes TXT answers skip the records the function selects, while an UPDATE still stores them: the record "never appears" for a checker but does exist, so a test can still see whether it was cleaned up. Nil shows everything again.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store holds the zones and records of the test server. It is safe for concurrent use. Names are compared in canonical form (lower case, fully qualified), so callers may pass "Host.Example.lan" or "host.example.lan.".
func (*Store) ChallengeRecords ¶
ChallengeRecords returns every TXT record whose name starts with _acme-challenge., sorted. A test that ends with an empty result proves the agent cleaned up.
func (*Store) DeleteTXT ¶
DeleteTXT removes one value (RFC 2136 §2.5.4) and reports whether it existed.
func (*Store) DeleteTXTSet ¶
DeleteTXTSet removes all TXT values of a name (RFC 2136 §2.5.2).
func (*Store) SetCNAME ¶
SetCNAME makes name an alias of target (CNAME delegation of _acme-challenge). An empty target removes the alias.