jarld obtains and renews a certificate for another host; the host asks
for it with one command, waits, downloads it when it is newer than its
copy and runs a hook with the paths in JARL_CERT_* variables.
- Certificates have an owner user; another user can't take the name.
An existing one is obtained again only when a name is added or
removed. A new certificates grant (names=) says which names a user
may have; it is never part of "*". Users may own
certificates.max_per_user certificates (10) or their own cert_limit.
- POST /certificates/{name}/request; owners may list, show, export and
delete theirs; keys only over HTTPS, the socket or loopback; every
download is recorded and shown as "Pulled by".
- CLI: jarl cert get (saved settings, all saved when no name), cert
saved, cert forget, cert schedule (daily systemd timer, Linux, root).
- Migration 14. Tests: server, auth, and e2e against Pebble.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
667 lines
24 KiB
Go
667 lines
24 KiB
Go
// Package api defines the JSON types of Jarl's HTTP API, shared by the
|
|
// server and the Go client used by the CLI.
|
|
package api
|
|
|
|
import (
|
|
"encoding/json"
|
|
"time"
|
|
|
|
"jarl/internal/dnssec"
|
|
"jarl/internal/model"
|
|
"jarl/internal/nscheck"
|
|
"jarl/internal/porkbun"
|
|
"jarl/internal/version"
|
|
)
|
|
|
|
// Version is the API path prefix.
|
|
const Prefix = "/api/v1"
|
|
|
|
// Zone is a zone as returned by the API.
|
|
type Zone struct {
|
|
model.Zone
|
|
Display string `json:"display_name"`
|
|
View string `json:"view,omitempty"`
|
|
Records int `json:"record_count"`
|
|
// DisabledRecords is how many of the records are disabled.
|
|
DisabledRecords int `json:"disabled_count,omitempty"`
|
|
ZoneFile string `json:"zone_file,omitempty"` // the file named loads
|
|
RName string `json:"rname_email,omitempty"`
|
|
// Registrar names the registrar Jarl can manage the domain at
|
|
// ("porkbun"), when one is configured for it.
|
|
Registrar string `json:"registrar,omitempty"`
|
|
// LinkedWith are the views of the zones this one is linked with
|
|
// (docs/views.md#linked-zones).
|
|
LinkedWith []string `json:"linked_with,omitempty"`
|
|
// Links are the zones this one is linked with, with their views.
|
|
Links []ZoneLink `json:"links,omitempty"`
|
|
// InViews are the zones of this name in the other views (any type),
|
|
// in view order: for going straight to one.
|
|
InViews []ZoneLink `json:"in_views,omitempty"`
|
|
// OtherViews are the other views with a primary zone of this name
|
|
// (linked or not): what GET /zones/{zone}/compare compares.
|
|
OtherViews []string `json:"other_views,omitempty"`
|
|
// Prefix is the network a reverse zone answers for; PTRMissing how
|
|
// many of its view's A and AAAA addresses in it have no PTR record
|
|
// (POST /zones/{zone}/fill-ptr adds them).
|
|
Prefix string `json:"prefix,omitempty"`
|
|
PTRMissing int `json:"ptr_missing,omitempty"`
|
|
// PTRMissingList are the first 25 of them: the PTR records adding
|
|
// them would create.
|
|
PTRMissingList []PTRFill `json:"ptr_missing_list,omitempty"`
|
|
// Pending is set when listing with a changeset: add, change or delete.
|
|
Pending string `json:"pending,omitempty"`
|
|
}
|
|
|
|
// Record is a record as returned by the API.
|
|
type Record struct {
|
|
model.Record
|
|
Zone string `json:"zone"`
|
|
View string `json:"view,omitempty"`
|
|
RelativeName string `json:"relative_name"`
|
|
EffectiveTTL uint32 `json:"effective_ttl"`
|
|
// Linked is "shared" or "local" for a record of a linked zone ("" otherwise).
|
|
Linked string `json:"linked,omitempty"`
|
|
// Text is the decoded value of TXT and SPF records.
|
|
Text *string `json:"text,omitempty"`
|
|
// Pending is set when listing with a changeset: add, change, delete,
|
|
// disable or enable.
|
|
Pending string `json:"pending,omitempty"`
|
|
}
|
|
|
|
// View is a view with its zone count.
|
|
type View struct {
|
|
model.View
|
|
Zones int `json:"zone_count"`
|
|
Color string `json:"color,omitempty"` // web UI colour, see model.ViewColors
|
|
// Limited is set for a view listed only because the principal can see
|
|
// zones in it (no views:read): only its name, colour and the zones
|
|
// they can see are given.
|
|
Limited bool `json:"limited,omitempty"`
|
|
}
|
|
|
|
// PTRFill is a PTR record a reverse zone lacks: Name (the PTR owner) for
|
|
// Address would give Target. Others are its other names; From the view
|
|
// whose record names it, when the zone's own view has none.
|
|
type PTRFill struct {
|
|
Address string `json:"address"`
|
|
Name string `json:"name"`
|
|
Target string `json:"target"`
|
|
Others []string `json:"others,omitempty"`
|
|
From string `json:"from,omitempty"`
|
|
}
|
|
|
|
// ViewColor sets the colour the web UI shows a view in.
|
|
type ViewColor struct {
|
|
Color string `json:"color"`
|
|
}
|
|
|
|
// ACL is an ACL with the objects that use it.
|
|
type ACL struct {
|
|
model.ACL
|
|
UsedBy []string `json:"used_by"`
|
|
}
|
|
|
|
// TSIGKey is a key; Secret is only filled when asked for and allowed.
|
|
type TSIGKey struct {
|
|
model.TSIGKey
|
|
UsedBy []string `json:"used_by"`
|
|
}
|
|
|
|
// Option is an option with display helpers.
|
|
type Option struct {
|
|
model.Option
|
|
Where string `json:"where"` // e.g. "view internal"
|
|
Description string `json:"description,omitempty"`
|
|
Status string `json:"status,omitempty"`
|
|
// Formatted is the value laid out over several lines, as in
|
|
// named.conf, when it has a block (for display and editing; Value is
|
|
// the same on one line).
|
|
Formatted string `json:"formatted,omitempty"`
|
|
}
|
|
|
|
// User is a user with formatted grants.
|
|
type User struct {
|
|
model.User
|
|
GrantStrings []string `json:"grant_strings"`
|
|
// TOTPRequired says that totp.require in jarl.yaml makes two-factor
|
|
// login compulsory for the user.
|
|
TOTPRequired bool `json:"totp_required,omitempty"`
|
|
}
|
|
|
|
// Token is an API token. Secret is only set when the token is created.
|
|
type Token struct {
|
|
model.Token
|
|
GrantStrings []string `json:"grant_strings,omitempty"`
|
|
Secret string `json:"token,omitempty"`
|
|
}
|
|
|
|
// Whoami describes the authenticated principal.
|
|
type Whoami struct {
|
|
User User `json:"user"`
|
|
Method string `json:"method"`
|
|
Token *Token `json:"token,omitempty"`
|
|
CSRFToken string `json:"csrf_token,omitempty"`
|
|
Permissions []string `json:"permissions"`
|
|
Admin bool `json:"admin"`
|
|
Version string `json:"version"`
|
|
// TOTP is the user's two-factor login (sessions only).
|
|
TOTP *TOTPStatus `json:"totp,omitempty"`
|
|
// TOTPSetupRequired: the user must set up two-factor login before
|
|
// doing anything else (totp.require).
|
|
TOTPSetupRequired bool `json:"totp_setup_required,omitempty"`
|
|
// Build is what the server was built from (release or commit).
|
|
Build version.Build `json:"build"`
|
|
}
|
|
|
|
// LoginChallenge answers a correct password of a user with two-factor
|
|
// login: send a code with the challenge to POST /auth/login/totp.
|
|
type LoginChallenge struct {
|
|
TOTPRequired bool `json:"totp_required"`
|
|
Challenge string `json:"challenge"`
|
|
}
|
|
|
|
// LoginTOTP is the second login step.
|
|
type LoginTOTP struct {
|
|
Challenge string `json:"challenge"`
|
|
// Code is the current code from the authenticator app, or a recovery
|
|
// code.
|
|
Code string `json:"code"`
|
|
}
|
|
|
|
// TOTPStatus is a user's two-factor login (GET /me/totp).
|
|
type TOTPStatus struct {
|
|
Enabled bool `json:"enabled"`
|
|
EnabledAt *time.Time `json:"enabled_at,omitempty"`
|
|
Required bool `json:"required"`
|
|
RecoveryCodesLeft int `json:"recovery_codes_left"`
|
|
// Policy is totp.require: none, admins or all.
|
|
Policy string `json:"policy"`
|
|
}
|
|
|
|
// TOTPSetupRequest starts setting up two-factor login.
|
|
type TOTPSetupRequest struct {
|
|
Password string `json:"password"`
|
|
}
|
|
|
|
// TOTPSetup is a new secret to put into an authenticator app: QR is the
|
|
// QR code of URI, as an image data: URI.
|
|
type TOTPSetup struct {
|
|
Secret string `json:"secret"`
|
|
URI string `json:"uri"`
|
|
QR string `json:"qr"`
|
|
Issuer string `json:"issuer"`
|
|
Account string `json:"account"`
|
|
}
|
|
|
|
// TOTPCode confirms a setup.
|
|
type TOTPCode struct {
|
|
Code string `json:"code"`
|
|
}
|
|
|
|
// TOTPDisable turns two-factor login off.
|
|
type TOTPDisable struct {
|
|
Password string `json:"password"`
|
|
Code string `json:"code"`
|
|
}
|
|
|
|
// RecoveryCodes are new recovery codes, shown once.
|
|
type RecoveryCodes struct {
|
|
Codes []string `json:"recovery_codes"`
|
|
}
|
|
|
|
// LoginRequest logs in.
|
|
type LoginRequest struct {
|
|
Username string `json:"username"`
|
|
Password string `json:"password"`
|
|
}
|
|
|
|
// ErrorBody is the error response.
|
|
type ErrorBody struct {
|
|
Error ErrorInfo `json:"error"`
|
|
}
|
|
|
|
// ErrorInfo describes an error.
|
|
type ErrorInfo struct {
|
|
Code string `json:"code"`
|
|
Message string `json:"message"`
|
|
Op int `json:"op,omitempty"`
|
|
Problems json.RawMessage `json:"problems,omitempty"`
|
|
Check json.RawMessage `json:"check,omitempty"`
|
|
Result json.RawMessage `json:"result,omitempty"`
|
|
}
|
|
|
|
// ChangeRequest is a request in a batch (POST /apply or changeset ops).
|
|
type ChangeRequest struct {
|
|
Op string `json:"op"`
|
|
ID int64 `json:"id,omitempty"`
|
|
BaseVersion int `json:"base_version,omitempty"`
|
|
Data json.RawMessage `json:"data,omitempty"`
|
|
}
|
|
|
|
// BatchRequest applies (or stages) several requests at once.
|
|
type BatchRequest struct {
|
|
Description string `json:"description,omitempty"`
|
|
Ops []ChangeRequest `json:"ops"`
|
|
DryRun bool `json:"dry_run,omitempty"`
|
|
Force bool `json:"force,omitempty"`
|
|
// AcceptRisk confirms a change that opens the server up
|
|
// (docs/exposure.md).
|
|
AcceptRisk bool `json:"accept_risk,omitempty"`
|
|
// Apply (for POST /changesets) applies the new changeset at once.
|
|
Apply bool `json:"apply,omitempty"`
|
|
}
|
|
|
|
// MutationResponse is returned by endpoints that change the configuration.
|
|
type MutationResponse struct {
|
|
Applied bool `json:"applied"`
|
|
Staged bool `json:"staged,omitempty"`
|
|
DryRun bool `json:"dry_run,omitempty"`
|
|
ChangesetID int64 `json:"changeset_id,omitempty"`
|
|
Result json.RawMessage `json:"result,omitempty"`
|
|
Changeset json.RawMessage `json:"changeset,omitempty"`
|
|
Added []model.Op `json:"added,omitempty"`
|
|
Warnings []string `json:"warnings,omitempty"`
|
|
Problems json.RawMessage `json:"problems,omitempty"`
|
|
Object json.RawMessage `json:"object,omitempty"`
|
|
}
|
|
|
|
// Changeset is a changeset as returned by the API.
|
|
type Changeset struct {
|
|
model.Changeset
|
|
Undoable bool `json:"undoable"`
|
|
}
|
|
|
|
// StatusResponse is GET /status.
|
|
type StatusResponse struct {
|
|
Version string `json:"version"`
|
|
Build version.Build `json:"build"`
|
|
Engine json.RawMessage `json:"engine"`
|
|
Time time.Time `json:"time"`
|
|
// ExpiringTokens are tokens that expire within TokenExpiryWarning or
|
|
// expired less than that long ago (not revoked): every user's for
|
|
// administrators, otherwise the caller's own.
|
|
ExpiringTokens []Token `json:"expiring_tokens"`
|
|
// Backup is the state of database backups (administrators only).
|
|
Backup *BackupStatus `json:"backup,omitempty"`
|
|
// TOTP is about two-factor login across users (administrators only).
|
|
TOTP *TOTPOverview `json:"totp,omitempty"`
|
|
// BlocklistErrors are blocklists whose last update failed (for those
|
|
// who may see blocking).
|
|
BlocklistErrors []BlocklistError `json:"blocklist_errors,omitempty"`
|
|
// BlockingPausedUntil is set while blocking is paused for a time,
|
|
// BlockingPausedIndefinitely while it is paused until resumed.
|
|
BlockingPausedUntil *time.Time `json:"blocking_paused_until,omitempty"`
|
|
BlockingPausedIndefinitely bool `json:"blocking_paused_indefinitely,omitempty"`
|
|
// Certificates sums up the TLS certificates Jarl manages
|
|
// (administrators only, when there are any).
|
|
Certificates *CertSummary `json:"certificates,omitempty"`
|
|
// EncryptedDNS is the last check of DNS over TLS and HTTPS, when it
|
|
// is set up (for those who may see options).
|
|
EncryptedDNS *EncDNSSummary `json:"encrypted_dns,omitempty"`
|
|
// Storage is the size of Jarl's databases and how full the disks Jarl
|
|
// uses are (administrators only).
|
|
Storage *Storage `json:"storage,omitempty"`
|
|
}
|
|
|
|
// Storage is the size of Jarl's databases and the disks Jarl uses.
|
|
type Storage struct {
|
|
Databases []Database `json:"databases"`
|
|
Total int64 `json:"total"` // the databases' bytes
|
|
Disks []Disk `json:"disks"`
|
|
}
|
|
|
|
// Database is one of Jarl's databases: its file with its -wal and -shm.
|
|
type Database struct {
|
|
Label string `json:"label"`
|
|
Path string `json:"path"`
|
|
Bytes int64 `json:"bytes"`
|
|
// Rows is how many answers the query log holds (statistics only),
|
|
// and QueryLogRetention how long it keeps them ("7d").
|
|
QueryLogRows *int64 `json:"query_log_rows,omitempty"`
|
|
QueryLogRetention string `json:"query_log_retention,omitempty"`
|
|
}
|
|
|
|
// Disk is a file system Jarl uses: what of Jarl's it holds, its size,
|
|
// what is free, and how much of it the databases take.
|
|
type Disk struct {
|
|
Path string `json:"path"`
|
|
Holds []string `json:"holds"`
|
|
Total int64 `json:"total"`
|
|
Free int64 `json:"free"`
|
|
Databases int64 `json:"databases"`
|
|
}
|
|
|
|
// CertSummary is what the dashboard reports about certificates.
|
|
type CertSummary struct {
|
|
Total int `json:"total"`
|
|
// Problems are the certificates that aren't fine: failing, expiring,
|
|
// expired (not ones still being obtained for the first time).
|
|
Problems []CertProblem `json:"problems"`
|
|
// Next is the certificate that expires first, and when.
|
|
Next string `json:"next,omitempty"`
|
|
NextAfter *time.Time `json:"next_after,omitempty"`
|
|
// Serving is the certificate jarld serves HTTPS with ("" for none or tls.cert_file).
|
|
Serving string `json:"serving,omitempty"`
|
|
}
|
|
|
|
// CertProblem is a certificate that needs attention.
|
|
type CertProblem struct {
|
|
Name string `json:"name"`
|
|
State string `json:"state"`
|
|
Message string `json:"message"`
|
|
}
|
|
|
|
// BlocklistError is a blocklist whose last update failed. UpdatedAt is
|
|
// the version named keeps using (nil: none yet).
|
|
type BlocklistError struct {
|
|
Name string `json:"name"`
|
|
Error string `json:"error"`
|
|
UpdatedAt *time.Time `json:"updated_at,omitempty"`
|
|
}
|
|
|
|
// TOTPOverview is what the dashboard reports about two-factor login.
|
|
type TOTPOverview struct {
|
|
// Policy is totp.require: none, admins or all.
|
|
Policy string `json:"policy"`
|
|
// Missing are enabled users who must use two-factor login and
|
|
// haven't set it up (they can do nothing else until they do).
|
|
Missing []string `json:"missing"`
|
|
// SharedAdmin is set when an enabled administrator called "admin"
|
|
// (the usual first account) exists next to other enabled
|
|
// administrators: it is probably shared, and worth disabling.
|
|
SharedAdmin string `json:"shared_admin,omitempty"`
|
|
}
|
|
|
|
// TokenExpiresHeader is sent with responses to a token that expires
|
|
// soon (model.TokenExpiryWarning), holding its expiry time (RFC 3339). The
|
|
// CLI warns its user when it sees it.
|
|
const TokenExpiresHeader = "Jarl-Token-Expires"
|
|
|
|
// BackupStatus describes the newest database backup, as recorded by
|
|
// 'jarld backup'.
|
|
type BackupStatus struct {
|
|
LastAt *time.Time `json:"last_at,omitempty"`
|
|
LastFile string `json:"last_file,omitempty"`
|
|
LastSize int64 `json:"last_size,omitempty"`
|
|
LastError string `json:"last_error,omitempty"`
|
|
// LastErrorAt is when the newest failed backup ran (only reported
|
|
// when it is newer than the last success).
|
|
LastErrorAt *time.Time `json:"last_error_at,omitempty"`
|
|
Dir string `json:"dir"`
|
|
// WarnAfter (seconds) is how old the newest backup may get before
|
|
// Stale is set (0: never).
|
|
WarnAfter int64 `json:"warn_after"`
|
|
Stale bool `json:"stale"`
|
|
}
|
|
|
|
// SearchResult is one search hit.
|
|
type SearchResult struct {
|
|
Kind string `json:"kind"` // zone, record, acl, view, key
|
|
ID int64 `json:"id"`
|
|
ZoneID int64 `json:"zone_id,omitempty"`
|
|
Label string `json:"label"`
|
|
Detail string `json:"detail,omitempty"`
|
|
}
|
|
|
|
// PasswordChange changes a password.
|
|
type PasswordChange struct {
|
|
Current string `json:"current_password,omitempty"`
|
|
Password string `json:"password"`
|
|
}
|
|
|
|
// UserInput creates or updates a user.
|
|
type UserInput struct {
|
|
Username *string `json:"username,omitempty"`
|
|
Password *string `json:"password,omitempty"`
|
|
Admin *bool `json:"admin,omitempty"`
|
|
Grants *[]model.Grant `json:"grants,omitempty"`
|
|
// GrantStrings are grants in compact form ("records:write zones=x").
|
|
GrantStrings *[]string `json:"grant_strings,omitempty"`
|
|
Role *string `json:"role,omitempty"` // a role template name
|
|
Disabled *bool `json:"disabled,omitempty"`
|
|
Comment *string `json:"comment,omitempty"`
|
|
// CertLimit is how many certificates the user may own (jarl cert
|
|
// get); a negative number goes back to certificates.max_per_user.
|
|
CertLimit *int `json:"cert_limit,omitempty"`
|
|
}
|
|
|
|
// TokenInput creates a token.
|
|
type TokenInput struct {
|
|
Name string `json:"name"`
|
|
Grants *[]model.Grant `json:"grants,omitempty"`
|
|
GrantStrings *[]string `json:"grant_strings,omitempty"`
|
|
Role string `json:"role,omitempty"`
|
|
ExpiresIn string `json:"expires_in,omitempty"` // e.g. "90d", "720h"
|
|
ExpiresAt *time.Time `json:"expires_at,omitempty"`
|
|
}
|
|
|
|
// TokenRotation gives a token a new secret (POST /tokens/{id}/rotate).
|
|
// Every field is optional.
|
|
type TokenRotation struct {
|
|
// Grace keeps the old secret working this long (e.g. "1h", "2d"; at
|
|
// most 7d), so clients can be updated without an outage. Default:
|
|
// the old secret stops at once.
|
|
Grace string `json:"grace,omitempty"`
|
|
// The new expiry. Default: a token that expires gets its lifetime
|
|
// again, counted from now; one that doesn't, still doesn't.
|
|
ExpiresIn string `json:"expires_in,omitempty"`
|
|
ExpiresAt *time.Time `json:"expires_at,omitempty"`
|
|
NoExpiry bool `json:"no_expiry,omitempty"`
|
|
}
|
|
|
|
// ZoneImport imports zone file text into a zone.
|
|
type ZoneImport struct {
|
|
Text string `json:"text"`
|
|
// Mode "merge" adds missing records; "replace" makes the zone equal
|
|
// to the file (deleting other records).
|
|
Mode string `json:"mode"`
|
|
DryRun bool `json:"dry_run,omitempty"`
|
|
// UseSOA also takes the SOA timers and default TTL from the file.
|
|
UseSOA bool `json:"use_soa,omitempty"`
|
|
}
|
|
|
|
// SerialsResponse is GET /zones/{zone}/serials.
|
|
type SerialsResponse struct {
|
|
Zone string `json:"zone"`
|
|
View string `json:"view,omitempty"`
|
|
Type string `json:"type"`
|
|
// Serial is what this server serves: named's loaded serial, or for a
|
|
// primary zone Jarl's when named can't be asked (SerialSource says
|
|
// which).
|
|
Serial *uint32 `json:"serial"`
|
|
SerialSource string `json:"serial_source,omitempty"`
|
|
Servers []nscheck.Result `json:"servers"`
|
|
Notes []string `json:"notes"`
|
|
CheckedAt time.Time `json:"checked_at"`
|
|
}
|
|
|
|
// DelegationResponse is GET /zones/{zone}/delegation.
|
|
type DelegationResponse struct {
|
|
*nscheck.DelegationReport
|
|
View string `json:"view,omitempty"`
|
|
Notes []string `json:"notes"`
|
|
CheckedAt time.Time `json:"checked_at"`
|
|
}
|
|
|
|
// DNSSECResponse is GET /zones/{zone}/dnssec.
|
|
type DNSSECResponse struct {
|
|
Zone string `json:"zone"`
|
|
View string `json:"view,omitempty"`
|
|
Type string `json:"type"`
|
|
*dnssec.Status
|
|
// DSAt says where the zone's DS record goes: "parent_zone" (a primary
|
|
// zone in Jarl, below), "registrar" (the zone is a registered domain),
|
|
// "parent" (a subdomain whose parent zone is hosted elsewhere),
|
|
// "reverse" (whoever delegates the addresses) or "none" (nothing on
|
|
// the internet delegates the zone, so it can't have one).
|
|
DSAt string `json:"ds_at"`
|
|
// DSPlace completes "add the DS record …" ("at your registrar"); ""
|
|
// for "none".
|
|
DSPlace string `json:"ds_place,omitempty"`
|
|
// DSNote explains DSAt "none".
|
|
DSNote string `json:"ds_note,omitempty"`
|
|
// ParentZone is set when the parent zone is a primary zone in Jarl
|
|
// (in the zone's own view, else preferably a public one): the DS
|
|
// record then goes there, as a record.
|
|
ParentZone string `json:"parent_zone,omitempty"`
|
|
ParentZoneID int64 `json:"parent_zone_id,omitempty"`
|
|
ParentView string `json:"parent_view,omitempty"`
|
|
// ParentDS is the DS records the parent zone in Jarl has for the
|
|
// zone (record data, e.g. "51126 13 2 FFBE...").
|
|
ParentDS []string `json:"parent_ds,omitempty"`
|
|
// Registrar names the registrar Jarl can publish the DS at
|
|
// ("porkbun"), when one is configured in jarl.yaml.
|
|
Registrar string `json:"registrar,omitempty"`
|
|
}
|
|
|
|
// CheckDSResponse is POST /zones/{zone}/dnssec/check-ds: what the parent
|
|
// zone has, and what named was told.
|
|
type CheckDSResponse struct {
|
|
Parent *nscheck.ParentDSReport `json:"parent"`
|
|
Marked []string `json:"marked"`
|
|
Notes []string `json:"notes"`
|
|
Status *dnssec.Status `json:"status"`
|
|
}
|
|
|
|
// DNSSECWipe is POST /zones/{zone}/dnssec/wipe.
|
|
type DNSSECWipe struct {
|
|
// Force wipes although the parent zone's DS records couldn't be
|
|
// checked, or named still counts a removed DS as cached.
|
|
Force bool `json:"force,omitempty"`
|
|
DryRun bool `json:"dry_run,omitempty"`
|
|
}
|
|
|
|
// DNSSECWipeResponse is the result of a wipe.
|
|
type DNSSECWipeResponse struct {
|
|
Removed []string `json:"removed"`
|
|
DryRun bool `json:"dry_run,omitempty"`
|
|
ChangesetID int64 `json:"changeset_id,omitempty"`
|
|
Parent *nscheck.ParentDSReport `json:"parent,omitempty"`
|
|
}
|
|
|
|
// RegistrarResponse is GET /zones/{zone}/registrar: the domain's
|
|
// delegation at the registrar, next to what the zone says.
|
|
type RegistrarResponse struct {
|
|
Registrar string `json:"registrar"` // "porkbun"
|
|
Domain string `json:"domain"`
|
|
// NS are the name servers at the registry, JarlNS those in the
|
|
// zone's NS records (both without trailing dots).
|
|
NS []string `json:"ns"`
|
|
JarlNS []string `json:"jarl_ns"`
|
|
NSMatch bool `json:"ns_match"`
|
|
// Glue covers every glue record at the registry and every name server
|
|
// inside the zone that needs one.
|
|
Glue []GlueStatus `json:"glue"`
|
|
// DS are the DS records at the registry.
|
|
DS []RegistrarDS `json:"ds"`
|
|
Findings []nscheck.Finding `json:"findings"`
|
|
// Error is set when the registrar couldn't be asked; the rest is
|
|
// then empty.
|
|
Error string `json:"error,omitempty"`
|
|
}
|
|
|
|
// GlueStatus compares a glue record at the registry with the zone.
|
|
type GlueStatus struct {
|
|
Host string `json:"host"`
|
|
Registry []string `json:"registry"` // addresses at the registry (none: no glue record)
|
|
Jarl []string `json:"jarl"` // the zone's A and AAAA records for the host
|
|
// Needed: a name server in the zone's NS records that is inside the
|
|
// domain, so resolvers need its glue. InUse: in the registry's NS.
|
|
Needed bool `json:"needed"`
|
|
InUse bool `json:"in_use"`
|
|
// Action is what syncing the glue does: "create", "update" or "".
|
|
Action string `json:"action,omitempty"`
|
|
}
|
|
|
|
// RegistrarDS is a DS record at the registry.
|
|
type RegistrarDS struct {
|
|
porkbun.DS
|
|
// Matches: it points at a key named publishes for the zone.
|
|
Matches bool `json:"matches"`
|
|
}
|
|
|
|
// RegistrarChange asks for a change at the registrar.
|
|
type RegistrarChange struct {
|
|
// NS (set-ns) are the name servers to set (default: the zone's NS
|
|
// records).
|
|
NS []string `json:"ns,omitempty"`
|
|
// KeyTag (publish DS) picks the key (default: every key that needs
|
|
// one).
|
|
KeyTag uint16 `json:"key_tag,omitempty"`
|
|
// Force skips the checks that the change won't break the domain.
|
|
Force bool `json:"force,omitempty"`
|
|
DryRun bool `json:"dry_run,omitempty"`
|
|
}
|
|
|
|
// RegistrarChangeResponse is the result of a change at the registrar.
|
|
type RegistrarChangeResponse struct {
|
|
// Done lists what was changed (or would be, in a dry run).
|
|
Done []string `json:"done"`
|
|
DryRun bool `json:"dry_run,omitempty"`
|
|
Checks []nscheck.Finding `json:"checks"`
|
|
Warnings []string `json:"warnings"`
|
|
}
|
|
|
|
// Blocklist is a blocklist as returned by the API (docs/blocking.md).
|
|
type Blocklist struct {
|
|
model.Blocklist
|
|
// Views are the views it applies to; AutoViews is set when that is
|
|
// "every view that offers recursion" (view_ids is empty).
|
|
Views []string `json:"views"`
|
|
AutoViews bool `json:"auto_views,omitempty"`
|
|
// State is ok, waiting (not downloaded yet), error (the last update
|
|
// failed; the previous version stays in use), disabled, or idle (it
|
|
// applies to no view).
|
|
State string `json:"state"`
|
|
Status *model.BlocklistStatus `json:"status,omitempty"`
|
|
// MemoryMB estimates what named needs for the list, in all its views.
|
|
MemoryMB int `json:"memory_mb,omitempty"`
|
|
Pending string `json:"pending,omitempty"`
|
|
// Step is the name of the step the list starts at ("normal" or one
|
|
// above it).
|
|
Step string `json:"step"`
|
|
}
|
|
|
|
// BlockStep is a blocking step above normal as returned by the API, with
|
|
// what uses it.
|
|
type BlockStep struct {
|
|
model.BlockStep
|
|
Lists []string `json:"lists"`
|
|
Groups []string `json:"groups"`
|
|
Pending string `json:"pending,omitempty"`
|
|
}
|
|
|
|
// ClientGroup is a client group as returned by the API.
|
|
type ClientGroup struct {
|
|
model.ClientGroup
|
|
Step string `json:"step"`
|
|
Views []string `json:"views"`
|
|
AutoViews bool `json:"auto_views,omitempty"`
|
|
Pending string `json:"pending,omitempty"`
|
|
}
|
|
|
|
// BlockRule is a block or allow rule as returned by the API.
|
|
type BlockRule struct {
|
|
model.BlockRule
|
|
Views []string `json:"views"`
|
|
AutoViews bool `json:"auto_views,omitempty"`
|
|
Pending string `json:"pending,omitempty"`
|
|
}
|
|
|
|
// ZoneLink is a zone a zone is linked with.
|
|
type ZoneLink struct {
|
|
ID int64 `json:"id"`
|
|
View string `json:"view"`
|
|
// Type and Linked are set in Zone.InViews.
|
|
Type string `json:"type,omitempty"`
|
|
Linked bool `json:"linked,omitempty"`
|
|
}
|
|
|
|
// EncDNSSummary is what the dashboard says about encrypted DNS.
|
|
type EncDNSSummary struct {
|
|
Checked time.Time `json:"checked"`
|
|
OK bool `json:"ok"`
|
|
Problems []string `json:"problems"`
|
|
Warnings []string `json:"warnings"`
|
|
}
|