Documentation ¶
Overview ¶
Package tailsql implements an HTTP API and "playground" UI for sending SQL queries to a collection of local and/or remote databases, and rendering the results for human consumption.
API ¶
The main UI is served from "/", static assets from "/static/". The following path and query parameters are understood:
The q parameter carries an SQL query. The syntax of the query depends on the src (see below). See also "Named Queries" below.
The src parameter names which database to query against. Its values are defined when the server is set up. If src is omitted, the first database is used as a default.
"/" serves output as HTML for the UI. In this format the query (q) may be empty (no output will be displayed).
"/json" serves output as JSON objects, one per row. In this format the query (q) must be non-empty.
"/csv" serves output as comma-separated values, the first line giving the column names, the remaining lines the rows. In this format the query (q) must be non-empty.
"/meta" serves a JSON blob of metadata about available data sources.
Calls to the /json endpoint must set the Sec-Tailsql header to "1". This prevents browser scripts from directing queries to this endpoint.
Calls to /csv must either set Sec-Tailsql to "1" or include a tailsqlQuery=1 same-site cookie.
Calls to the UI with a non-empty query must include the tailsqlQuery=1 same-site cookie, which is set when the UI first loads. This averts simple cross-site redirection tricks.
Named Queries ¶
The query processor treats a query of the form "named:<string>" as a named query. Named queries are SQL queries pre-defined by the database, to allow users to make semantically stable queries without relying on a specific schema format.
Meta Queries ¶
The query processor treats a query "meta:named" as a meta-query to report the names and content of all named queries, regardless of source.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func UnmarshalOptions ¶
UnmarshalOptions unmarshals a HuJSON Config value into opts.
Types ¶
type DBOptions ¶
type DBOptions struct { // Label is a human-readable descriptive label to show to users when // rendering this database in a UI. Label string // NamedQueries is a map from names to SQL query text, that the service // should allow as pre-defined queries for this database. // // Unlike user-saved queries, named queries allow the database to change the // query when the underlying schema changes while preserving the semantics // the user observes. NamedQueries map[string]string }
DBOptions are optional settings for a database. A nil *DBoptions is ready for use and provides defaults as described.
type DBSpec ¶
type DBSpec struct { Source string `json:"source"` // UI slug Label string `json:"label,omitempty"` // descriptive label Driver string `json:"driver,omitempty"` // e.g., "sqlite", "snowflake" // Named is an optional map of named SQL queries the database should expose. Named map[string]string `json:"named,omitempty"` URL string `json:"url,omitempty"` // path or connection URL KeyFile string `json:"keyFile,omitempty"` // path to key file Secret string `json:"secret,omitempty"` // name of secret }
A DBSpec describes a database that the server should use.
type Duration ¶
Duration is a wrapper for a time.Duration that allows it to marshal more legibly in JSON, using the standard Go notation.
func (Duration) MarshalText ¶
func (*Duration) UnmarshalText ¶
type LocalClient ¶
LocalClient is the subset of the tailscale.LocalClient interface required by the Server. It is defined here so that the caller can substitute a fake for testing and debugging.
type Options ¶
type Options struct { // The tailnet hostname the server should run on (required). Hostname string `json:"hostname,omitempty"` // The directory for tailscale state and configurations (optional). // If omitted or empty, the default location is used. StateDir string `json:"stateDir,omitempty"` // If true, serve HTTPS instead of HTTP. ServeHTTPS bool `json:"serveHTTPS,omitempty"` // If non-empty, a SQLite database URL to use for local state. LocalState string `json:"localState,omitempty"` // If non-empty, and LocalState is defined, export a read-only copy of the // local state database as a source with this name. LocalSource string `json:"localSource,omitempty"` // Databases that the server will allow queries against (optional). Sources []DBSpec `json:"sources,omitempty"` // Additional links that should be propagated to the UI. UILinks []UILink `json:"links,omitempty"` // The maximum timeout for a database query (0 means no timeout). QueryTimeout Duration `json:"queryTimeout,omitempty"` // A connection to tailscaled for authorization checks. If nil, no // authorization checks are performed and all requests are permitted. LocalClient LocalClient `json:"-"` // If non-nil, the server will add metrics to this map. The caller is // responsible for ensuring the map is published. Metrics *expvar.Map `json:"-"` // If non-nil and a LocalClient is available, Authorize is called for each // request giving the requested database src and the caller's WhoIs record. // If it reports an error, the request is failed. // // If Authorize is nil and a LocalClient is available, the default rule is // to accept any logged-in user, rejecting tagged nodes. // // If no LocalClient is available, this field is ignored, no authorization // checks are performed, and all requests are accepted. Authorize func(src string, info *apitype.WhoIsResponse) error `json:"-"` // If non-nil, use this store to fetch secret values. This is required if // any of the sources specifies a named secret for its connection string. SecretStore *setec.Store `json:"-"` // Optional rules to apply when rendering text for presentation in the UI. // After generating the value string, each rule is matched in order, and the // first match (if any) is applied to rewrite the output. The value returned // by the rule replaces the original string. UIRewriteRules []UIRewriteRule `json:"-"` // If non-nil, send logs to this logger. If nil, use log.Printf. Logf logger.Logf `json:"-"` }
Options describes settings for a Server.
func (Options) CheckSources ¶
CheckSources validates the sources of o. If this succeeds, it also returns a slice of any secret names required by the specified sources, if any.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is a server for the tailsql API.
func (*Server) Close ¶
Close closes all the database handles held by s and returns the join of their errors.
func (*Server) SetDB ¶
SetDB adds or replaces the database associated with the specified source in s with the given open db and options.
If a database was already open for the given source, its value is replaced, the old database handle is closed, and SetDB reports true.
If no database was already open for the given source, a new source is added and SetDB reports false.
type UIRewriteRule ¶
type UIRewriteRule struct { Column *regexp.Regexp // pattern for the column name (nil matches all) Value *regexp.Regexp // pattern for the value (nil matches all) // The Apply function takes the name of a column, the input value, and the // result of matching the value regexp (if any). Its return value replaces // the input when the value is rendered. If Apply == nil, the input is not // modified. // // As a special case, if Apply returns a nil value, the rule evaluator skips // the rule as if it had not matched, and goes on to the next rule. Apply func(column, input string, valueMatch []string) any }
UIRewriteRule is a rewriting rule for rendering output in HTML.
A rule matches a value if:
- Its Column regexp is empty or matches the column name, and
- Its Value regexp is empty or matches the value string
If a rule matches, its Apply function is called.
func (UIRewriteRule) CheckApply ¶
func (u UIRewriteRule) CheckApply(column, input string) (bool, any)
CheckApply reports whether u matches the specified column and input, and if so returns the result of applying u to it.