Documentation
¶
Overview ¶
Package api is the HTTP interface every Wegweiser client speaks.
The web interface and the weg command line are both clients of it, and neither reaches the database any other way (architecture invariant 1). What the API accepts is described in openapi.yaml, which is the source of truth: the models, the server interface and the client in gen/ are all generated from it, so an endpoint that is not written down there does not exist.
Index ¶
- Constants
- Variables
- func EnsureBootstrapToken(ctx context.Context, s store.Store, a *apply.Applier, now time.Time) (secret string, err error)
- func MintToken(name string, scopes []Scope, now time.Time) (secret string, tok store.Token, err error)
- type Cluster
- type Config
- type Notifier
- type Scope
- type Secondaries
- type Server
- func (s *Server) CheckZone(ctx context.Context, req gen.CheckZoneRequestObject) (gen.CheckZoneResponseObject, error)
- func (s *Server) Close() error
- func (s *Server) CreateRecord(ctx context.Context, req gen.CreateRecordRequestObject) (gen.CreateRecordResponseObject, error)
- func (s *Server) CreateSession(ctx context.Context, req gen.CreateSessionRequestObject) (gen.CreateSessionResponseObject, error)
- func (s *Server) CreateTSIGKey(ctx context.Context, req gen.CreateTSIGKeyRequestObject) (gen.CreateTSIGKeyResponseObject, error)
- func (s *Server) CreateToken(ctx context.Context, req gen.CreateTokenRequestObject) (gen.CreateTokenResponseObject, error)
- func (s *Server) CreateZone(ctx context.Context, req gen.CreateZoneRequestObject) (gen.CreateZoneResponseObject, error)
- func (s *Server) DeleteRecord(ctx context.Context, req gen.DeleteRecordRequestObject) (gen.DeleteRecordResponseObject, error)
- func (s *Server) DeleteSession(ctx context.Context, _ gen.DeleteSessionRequestObject) (gen.DeleteSessionResponseObject, error)
- func (s *Server) DeleteZone(ctx context.Context, req gen.DeleteZoneRequestObject) (gen.DeleteZoneResponseObject, error)
- func (s *Server) DetachRecord(ctx context.Context, req gen.DetachRecordRequestObject) (gen.DetachRecordResponseObject, error)
- func (s *Server) ExportZone(ctx context.Context, req gen.ExportZoneRequestObject) (gen.ExportZoneResponseObject, error)
- func (s *Server) Forwarded() http.Handler
- func (s *Server) GetCluster(ctx context.Context, _ gen.GetClusterRequestObject) (gen.GetClusterResponseObject, error)
- func (s *Server) GetCommit(ctx context.Context, req gen.GetCommitRequestObject) (gen.GetCommitResponseObject, error)
- func (s *Server) GetHealth(_ context.Context, _ gen.GetHealthRequestObject) (gen.GetHealthResponseObject, error)
- func (s *Server) GetMetrics(_ context.Context, _ gen.GetMetricsRequestObject) (gen.GetMetricsResponseObject, error)
- func (s *Server) GetRecord(ctx context.Context, req gen.GetRecordRequestObject) (gen.GetRecordResponseObject, error)
- func (s *Server) GetSecondaryConfig(ctx context.Context, req gen.GetSecondaryConfigRequestObject) (gen.GetSecondaryConfigResponseObject, error)
- func (s *Server) GetSecondaryStatus(_ context.Context, _ gen.GetSecondaryStatusRequestObject) (gen.GetSecondaryStatusResponseObject, error)
- func (s *Server) GetSession(ctx context.Context, _ gen.GetSessionRequestObject) (gen.GetSessionResponseObject, error)
- func (s *Server) GetSettings(ctx context.Context, _ gen.GetSettingsRequestObject) (gen.GetSettingsResponseObject, error)
- func (s *Server) GetZone(ctx context.Context, req gen.GetZoneRequestObject) (gen.GetZoneResponseObject, error)
- func (s *Server) ImportZone(ctx context.Context, req gen.ImportZoneRequestObject) (gen.ImportZoneResponseObject, error)
- func (s *Server) InitCluster(ctx context.Context, _ gen.InitClusterRequestObject) (gen.InitClusterResponseObject, error)
- func (s *Server) ListCommits(ctx context.Context, req gen.ListCommitsRequestObject) (gen.ListCommitsResponseObject, error)
- func (s *Server) ListRecords(ctx context.Context, req gen.ListRecordsRequestObject) (gen.ListRecordsResponseObject, error)
- func (s *Server) ListTSIGKeys(ctx context.Context, _ gen.ListTSIGKeysRequestObject) (gen.ListTSIGKeysResponseObject, error)
- func (s *Server) ListTokens(ctx context.Context, _ gen.ListTokensRequestObject) (gen.ListTokensResponseObject, error)
- func (s *Server) ListZones(ctx context.Context, req gen.ListZonesRequestObject) (gen.ListZonesResponseObject, error)
- func (s *Server) MakeRecordCanonical(ctx context.Context, req gen.MakeRecordCanonicalRequestObject) (gen.MakeRecordCanonicalResponseObject, error)
- func (s *Server) ReadTSIGKeySecret(ctx context.Context, req gen.ReadTSIGKeySecretRequestObject) (gen.ReadTSIGKeySecretResponseObject, error)
- func (s *Server) ReconcileZone(ctx context.Context, req gen.ReconcileZoneRequestObject) (gen.ReconcileZoneResponseObject, error)
- func (s *Server) RemoveClusterMember(ctx context.Context, req gen.RemoveClusterMemberRequestObject) (gen.RemoveClusterMemberResponseObject, error)
- func (s *Server) ReplaceRRsets(ctx context.Context, req gen.ReplaceRRsetsRequestObject) (gen.ReplaceRRsetsResponseObject, error)
- func (s *Server) RevokeTSIGKey(ctx context.Context, req gen.RevokeTSIGKeyRequestObject) (gen.RevokeTSIGKeyResponseObject, error)
- func (s *Server) RevokeToken(ctx context.Context, req gen.RevokeTokenRequestObject) (gen.RevokeTokenResponseObject, error)
- func (s *Server) RollbackZone(ctx context.Context, req gen.RollbackZoneRequestObject) (gen.RollbackZoneResponseObject, error)
- func (s *Server) StreamQueries(ctx context.Context, request gen.StreamQueriesRequestObject) (gen.StreamQueriesResponseObject, error)
- func (s *Server) UpdateRecord(ctx context.Context, req gen.UpdateRecordRequestObject) (gen.UpdateRecordResponseObject, error)
- func (s *Server) UpdateSettings(ctx context.Context, req gen.UpdateSettingsRequestObject) (gen.UpdateSettingsResponseObject, error)
- func (s *Server) UpdateZone(ctx context.Context, req gen.UpdateZoneRequestObject) (gen.UpdateZoneResponseObject, error)
- type Snapshots
Constants ¶
const BootstrapName = "bootstrap"
BootstrapName is the name the first token carries, so that an operator listing tokens can see which one came from the installer rather than from a person.
const TokenPrefix = "weg_"
TokenPrefix marks a secret as one of ours, so that a token pasted into the wrong field is recognisable in a log and a secret scanner has something to match on.
Variables ¶
var ErrTokenInvalid = errors.New("api: the token is not valid")
ErrTokenInvalid is what every failed authentication returns.
Unknown, revoked and expired are one error on purpose: three would let an attacker sort guesses into "wrong" and "used to be right" (D5).
Functions ¶
func EnsureBootstrapToken ¶
func EnsureBootstrapToken( ctx context.Context, s store.Store, a *apply.Applier, now time.Time, ) (secret string, err error)
EnsureBootstrapToken creates the first admin token if the database has none, and returns the secret exactly once.
An empty secret means tokens already existed and nothing was created. There is no way to ask for the secret again: what is stored is a hash, so a lost bootstrap token is replaced rather than recovered (docs/decisions/ D5).
Types ¶
type Cluster ¶ added in v0.5.0
type Cluster interface {
// Init starts a cluster with this node as its only member. The API runs
// it with no write in flight, which is what it asks of its caller.
Init(ctx context.Context) error
// Member is the identifier this node is a member by, and the address the
// others reach it at.
Member() (id, addr string)
// Status is what this member knows of the cluster and of itself.
Status(ctx context.Context) (cluster.Status, error)
// Replicating reports whether this node is a member of a cluster yet.
Replicating() bool
// IsLeader reports whether this member leads.
IsLeader() bool
// Leader names the member leading, empty while none is.
Leader() (id, addr string)
// Remove takes a member out of the cluster. Only the leader can.
Remove(id string) error
// Left says why this member no longer takes part in the cluster, and is
// nil while it does.
Left() error
// DialForward opens a stream to the member at addr that carries a
// forwarded write.
DialForward(ctx context.Context, addr string) (net.Conn, error)
}
Cluster is this node's member of a cluster, as far as the API acts on it. A *cluster.Node is one.
Of the cluster itself the API learns two things, whether this member leads and where the leader is, which is what forwarding a write takes (docs/decisions/d40-a-write-reaches-the-leader.md).
type Config ¶
type Config struct {
// Store is the source of truth. It is read directly and written only
// through the applier.
Store store.Store
// Applier is the write path. Everything this server stores goes through
// it, zones and the tokens, keys and settings beside them, so that there
// is one place a change is decided (architecture invariant 4).
Applier *apply.Applier
// Snapshots is what the query path answers from, read for /healthz and
// for the version a notification announces. A nil one means the API is
// running without a query path, which is what a test does.
Snapshots Snapshots
// Secondaries is where each secondary stands, for the status endpoint.
// Optional; without it there is nothing to report.
Secondaries Secondaries
// Notifier tells the secondaries a zone changed, once the snapshot saying
// so has been published (docs/decisions/d27-notify.md). May be nil, and then
// nobody is told and a secondary waits out its refresh timer.
Notifier Notifier
// Metrics is what /metrics exports. It is required rather than optional:
// an endpoint that answers with an empty registry when the process forgot
// to build one would report a server that answers no queries, which is
// worse than no endpoint at all.
Metrics *metrics.Metrics
// Stream is what the live query stream subscribes to. Required for the
// same reason as Metrics: an endpoint that opens a stream nothing feeds
// looks like a server nobody is querying.
Stream *stream.Hub
// Cluster is nil when the configuration file has no cluster section, and
// then this node is a single server and every cluster endpoint says so.
Cluster Cluster
// UI decides whether the embedded web interface is served alongside the
// API. False serves only the API and answers everything else with a
// problem document saying so (docs/decisions/ D16).
UI bool
// OnError is called for failures the client is not told the detail of, so
// that they reach an operator instead of nobody. It may be nil.
OnError func(error)
// Now supplies the current time. Nil picks [time.Now]; tests set it.
Now func() time.Time
}
Config is what a Server needs.
type Notifier ¶ added in v0.2.0
Notifier tells the secondaries that a zone has a new version. A *dns.Notifier is one. Who they are is copied from the store beside everything else the query path holds, not by the API.
type Scope ¶
type Scope string
Scope is a permission a token carries.
The scopes a token may carry. They are ordered: admin allows everything write allows, and write allows everything read allows. Three levels rather than a permission per endpoint, because a permission model nobody can hold in their head is one that gets granted wholesale.
type Secondaries ¶ added in v0.3.0
type Secondaries interface {
Standing() []dns.ProbeStanding
}
Secondaries reports where each secondary stands on each zone, as the probes have found it. A *dns.Prober is one.
It is optional. A server running without one knows nothing about any secondary and says so by having nothing to report, which is the same answer a server whose notify list is empty gives.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server implements the generated API.
func (*Server) CheckZone ¶ added in v0.2.0
func (s *Server) CheckZone( ctx context.Context, req gen.CheckZoneRequestObject, ) (gen.CheckZoneResponseObject, error)
CheckZone reports what is wrong with a zone as it stands.
func (*Server) Close ¶
Close stops the background work the server does and writes out what it was holding.
It is safe to call more than once, and a server that is closed still serves: the handler does not depend on any of this, so a request arriving during shutdown is answered rather than dropped.
func (*Server) CreateRecord ¶
func (s *Server) CreateRecord( ctx context.Context, req gen.CreateRecordRequestObject, ) (gen.CreateRecordResponseObject, error)
CreateRecord adds a record to a zone.
What adding it caused comes back with it. An address record may generate a PTR, may find that the address already answers with another name, or may find no reverse zone to put anything in, and the last two are not errors. They are decisions for a person, so they travel as data (docs/decisions/ D3 and D6).
func (*Server) CreateSession ¶
func (s *Server) CreateSession( ctx context.Context, req gen.CreateSessionRequestObject, ) (gen.CreateSessionResponseObject, error)
CreateSession exchanges a token for a browser session.
func (*Server) CreateTSIGKey ¶ added in v0.2.0
func (s *Server) CreateTSIGKey( ctx context.Context, req gen.CreateTSIGKeyRequestObject, ) (gen.CreateTSIGKeyResponseObject, error)
CreateTSIGKey stores a key and returns its secret.
func (*Server) CreateToken ¶
func (s *Server) CreateToken( ctx context.Context, req gen.CreateTokenRequestObject, ) (gen.CreateTokenResponseObject, error)
CreateToken mints a token and shows its secret for the only time.
func (*Server) CreateZone ¶
func (s *Server) CreateZone( ctx context.Context, req gen.CreateZoneRequestObject, ) (gen.CreateZoneResponseObject, error)
CreateZone brings a zone into existence.
func (*Server) DeleteRecord ¶
func (s *Server) DeleteRecord( ctx context.Context, req gen.DeleteRecordRequestObject, ) (gen.DeleteRecordResponseObject, error)
DeleteRecord removes a record, and whatever was generated from it.
func (*Server) DeleteSession ¶
func (s *Server) DeleteSession( ctx context.Context, _ gen.DeleteSessionRequestObject, ) (gen.DeleteSessionResponseObject, error)
DeleteSession ends the session, if the request came with one.
func (*Server) DeleteZone ¶
func (s *Server) DeleteZone( ctx context.Context, req gen.DeleteZoneRequestObject, ) (gen.DeleteZoneResponseObject, error)
DeleteZone removes a zone and everything in it.
func (*Server) DetachRecord ¶
func (s *Server) DetachRecord( ctx context.Context, req gen.DetachRecordRequestObject, ) (gen.DetachRecordResponseObject, error)
DetachRecord turns a generated record into an authored one.
This is the way out of "a generated record cannot be edited" (D4). A record that is already authored comes back unchanged rather than as an error, which makes calling this twice harmless.
func (*Server) ExportZone ¶
func (s *Server) ExportZone( ctx context.Context, req gen.ExportZoneRequestObject, ) (gen.ExportZoneResponseObject, error)
ExportZone writes a zone out in the format every other authoritative server reads.
func (*Server) Forwarded ¶ added in v0.5.0
Forwarded is what the cluster port serves writes forwarded to this member with. The member that forwarded one authenticated its caller and says who it was, and the cluster port is reached only by members holding the secret, which is what makes saying so enough (D40, D43). A write is never forwarded on from here: one that arrives after leadership moved is refused, and the member it came from answers with that.
func (*Server) GetCluster ¶ added in v0.5.0
func (s *Server) GetCluster( ctx context.Context, _ gen.GetClusterRequestObject, ) (gen.GetClusterResponseObject, error)
GetCluster says who the members are, as this node knows them, and how far each has got (docs/decisions/d42-membership-lives-in-the-log.md). The others are asked as it answers, unless another member is the one asking (docs/decisions/d47-status-asks-every-member.md).
func (*Server) GetCommit ¶
func (s *Server) GetCommit( ctx context.Context, req gen.GetCommitRequestObject, ) (gen.GetCommitResponseObject, error)
GetCommit returns one commit with everything it changed.
func (*Server) GetHealth ¶
func (s *Server) GetHealth(_ context.Context, _ gen.GetHealthRequestObject) (gen.GetHealthResponseObject, error)
GetHealth reports whether the server is fit to answer queries.
func (*Server) GetMetrics ¶
func (s *Server) GetMetrics( _ context.Context, _ gen.GetMetricsRequestObject, ) (gen.GetMetricsResponseObject, error)
GetMetrics writes the current values in the Prometheus text exposition format.
func (*Server) GetRecord ¶
func (s *Server) GetRecord( ctx context.Context, req gen.GetRecordRequestObject, ) (gen.GetRecordResponseObject, error)
GetRecord returns one record.
func (*Server) GetSecondaryConfig ¶ added in v0.2.0
func (s *Server) GetSecondaryConfig( ctx context.Context, req gen.GetSecondaryConfigRequestObject, ) (gen.GetSecondaryConfigResponseObject, error)
GetSecondaryConfig writes the configuration the other end of a transfer needs, and says what about the arrangement will stop it working.
func (*Server) GetSecondaryStatus ¶ added in v0.3.0
func (s *Server) GetSecondaryStatus( _ context.Context, _ gen.GetSecondaryStatusRequestObject, ) (gen.GetSecondaryStatusResponseObject, error)
GetSecondaryStatus says where each secondary stands on each zone.
A plain read: it carries no secret, only addresses that are already on the notify list, zone names this server is authoritative for, and serials it answers with.
func (*Server) GetSession ¶
func (s *Server) GetSession( ctx context.Context, _ gen.GetSessionRequestObject, ) (gen.GetSessionResponseObject, error)
GetSession reports who the request is authenticated as.
func (*Server) GetSettings ¶
func (s *Server) GetSettings( ctx context.Context, _ gen.GetSettingsRequestObject, ) (gen.GetSettingsResponseObject, error)
GetSettings reports the defaults a zone that says nothing inherits.
func (*Server) GetZone ¶
func (s *Server) GetZone( ctx context.Context, req gen.GetZoneRequestObject, ) (gen.GetZoneResponseObject, error)
GetZone returns one zone.
func (*Server) ImportZone ¶
func (s *Server) ImportZone( ctx context.Context, req gen.ImportZoneRequestObject, ) (gen.ImportZoneResponseObject, error)
ImportZone brings a whole zone in from a file in the format of RFC 1035 §5.
func (*Server) InitCluster ¶ added in v0.5.0
func (s *Server) InitCluster( ctx context.Context, _ gen.InitClusterRequestObject, ) (gen.InitClusterResponseObject, error)
InitCluster starts a cluster with this node as its first member (docs/decisions/d44-starting-and-joining.md).
func (*Server) ListCommits ¶
func (s *Server) ListCommits( ctx context.Context, req gen.ListCommitsRequestObject, ) (gen.ListCommitsResponseObject, error)
ListCommits returns one page of history, newest first.
func (*Server) ListRecords ¶
func (s *Server) ListRecords( ctx context.Context, req gen.ListRecordsRequestObject, ) (gen.ListRecordsResponseObject, error)
ListRecords returns one page of a zone's records.
func (*Server) ListTSIGKeys ¶ added in v0.2.0
func (s *Server) ListTSIGKeys( ctx context.Context, _ gen.ListTSIGKeysRequestObject, ) (gen.ListTSIGKeysResponseObject, error)
ListTSIGKeys returns every key, revoked ones included.
func (*Server) ListTokens ¶
func (s *Server) ListTokens( ctx context.Context, _ gen.ListTokensRequestObject, ) (gen.ListTokensResponseObject, error)
ListTokens returns every token, revoked and expired ones included.
func (*Server) ListZones ¶
func (s *Server) ListZones( ctx context.Context, req gen.ListZonesRequestObject, ) (gen.ListZonesResponseObject, error)
ListZones returns one page of zones.
func (*Server) MakeRecordCanonical ¶ added in v0.2.0
func (s *Server) MakeRecordCanonical( ctx context.Context, req gen.MakeRecordCanonicalRequestObject, ) (gen.MakeRecordCanonicalResponseObject, error)
MakeRecordCanonical hands the reverse entry for an address to this record.
It is the answer to a conflict that D3 asked for and D33 put here: the check says which name an address reverses to, and this is how somebody changes it.
func (*Server) ReadTSIGKeySecret ¶ added in v0.2.0
func (s *Server) ReadTSIGKeySecret( ctx context.Context, req gen.ReadTSIGKeySecretRequestObject, ) (gen.ReadTSIGKeySecretResponseObject, error)
ReadTSIGKeySecret returns the secret of one key.
func (*Server) ReconcileZone ¶ added in v0.2.0
func (s *Server) ReconcileZone( ctx context.Context, req gen.ReconcileZoneRequestObject, ) (gen.ReconcileZoneResponseObject, error)
ReconcileZone writes the reverse entries a zone's records imply and it does not have.
func (*Server) RemoveClusterMember ¶ added in v0.5.0
func (s *Server) RemoveClusterMember( ctx context.Context, req gen.RemoveClusterMemberRequestObject, ) (gen.RemoveClusterMemberResponseObject, error)
RemoveClusterMember takes a member out of the cluster. The request reaches the leader wherever it was sent (docs/decisions/d44-starting-and-joining.md).
func (*Server) ReplaceRRsets ¶
func (s *Server) ReplaceRRsets( ctx context.Context, req gen.ReplaceRRsetsRequestObject, ) (gen.ReplaceRRsetsResponseObject, error)
ReplaceRRsets makes the named RRsets exactly what the client sent.
func (*Server) RevokeTSIGKey ¶ added in v0.2.0
func (s *Server) RevokeTSIGKey( ctx context.Context, req gen.RevokeTSIGKeyRequestObject, ) (gen.RevokeTSIGKeyResponseObject, error)
RevokeTSIGKey withdraws a key and clears its secret.
func (*Server) RevokeToken ¶
func (s *Server) RevokeToken( ctx context.Context, req gen.RevokeTokenRequestObject, ) (gen.RevokeTokenResponseObject, error)
RevokeToken withdraws a token.
func (*Server) RollbackZone ¶
func (s *Server) RollbackZone( ctx context.Context, req gen.RollbackZoneRequestObject, ) (gen.RollbackZoneResponseObject, error)
RollbackZone restores a zone to the state it had at a serial.
func (*Server) StreamQueries ¶
func (s *Server) StreamQueries( ctx context.Context, request gen.StreamQueriesRequestObject, ) (gen.StreamQueriesResponseObject, error)
StreamQueries carries a live tail of the exchanges matching the filter, as Server-Sent Events.
func (*Server) UpdateRecord ¶
func (s *Server) UpdateRecord( ctx context.Context, req gen.UpdateRecordRequestObject, ) (gen.UpdateRecordResponseObject, error)
UpdateRecord changes a record, keeping its identity.
func (*Server) UpdateSettings ¶
func (s *Server) UpdateSettings( ctx context.Context, req gen.UpdateSettingsRequestObject, ) (gen.UpdateSettingsResponseObject, error)
UpdateSettings changes them. A field the request leaves out is left alone, so a client may send only what it means to change.
func (*Server) UpdateZone ¶
func (s *Server) UpdateZone( ctx context.Context, req gen.UpdateZoneRequestObject, ) (gen.UpdateZoneResponseObject, error)
UpdateZone changes a zone's own settings, leaving its records alone.
type Snapshots ¶
Snapshots is the data plane, as far as the API needs to know about it: what is being answered from. A *dns.Server is one.
The API only reads it. What is answered from next is published by whatever applied the change, on every node, and a handler is not that (docs/decisions/d41-what-follows-applying-a-batch.md).