Files
tailscale/tailcfg/tka.go
Will Norris 3ec5be3f51 all: remove AUTHORS file and references to it
This file was never truly necessary and has never actually been used in
the history of Tailscale's open source releases.

A Brief History of AUTHORS files
---

The AUTHORS file was a pattern developed at Google, originally for
Chromium, then adopted by Go and a bunch of other projects. The problem
was that Chromium originally had a copyright line only recognizing
Google as the copyright holder. Because Google (and most open source
projects) do not require copyright assignemnt for contributions, each
contributor maintains their copyright. Some large corporate contributors
then tried to add their own name to the copyright line in the LICENSE
file or in file headers. This quickly becomes unwieldy, and puts a
tremendous burden on anyone building on top of Chromium, since the
license requires that they keep all copyright lines intact.

The compromise was to create an AUTHORS file that would list all of the
copyright holders. The LICENSE file and source file headers would then
include that list by reference, listing the copyright holder as "The
Chromium Authors".

This also become cumbersome to simply keep the file up to date with a
high rate of new contributors. Plus it's not always obvious who the
copyright holder is. Sometimes it is the individual making the
contribution, but many times it may be their employer. There is no way
for the proejct maintainer to know.

Eventually, Google changed their policy to no longer recommend trying to
keep the AUTHORS file up to date proactively, and instead to only add to
it when requested: https://opensource.google/docs/releasing/authors.
They are also clear that:

> Adding contributors to the AUTHORS file is entirely within the
> project's discretion and has no implications for copyright ownership.

It was primarily added to appease a small number of large contributors
that insisted that they be recognized as copyright holders (which was
entirely their right to do). But it's not truly necessary, and not even
the most accurate way of identifying contributors and/or copyright
holders.

In practice, we've never added anyone to our AUTHORS file. It only lists
Tailscale, so it's not really serving any purpose. It also causes
confusion because Tailscalars put the "Tailscale Inc & AUTHORS" header
in other open source repos which don't actually have an AUTHORS file, so
it's ambiguous what that means.

Instead, we just acknowledge that the contributors to Tailscale (whoever
they are) are copyright holders for their individual contributions. We
also have the benefit of using the DCO (developercertificate.org) which
provides some additional certification of their right to make the
contribution.

The source file changes were purely mechanical with:

    git ls-files | xargs sed -i -e 's/\(Tailscale Inc &\) AUTHORS/\1 contributors/g'

Updates #cleanup

Change-Id: Ia101a4a3005adb9118051b3416f5a64a4a45987d
Signed-off-by: Will Norris <will@tailscale.com>
2026-01-23 15:49:45 -08:00

265 lines
8.9 KiB
Go

// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause
package tailcfg
import (
"tailscale.com/types/key"
"tailscale.com/types/tkatype"
)
// TKAInitBeginRequest submits a genesis AUM to seed the creation of the
// tailnet's key authority.
type TKAInitBeginRequest struct {
// Version is the client's capabilities.
Version CapabilityVersion
// NodeKey is the client's current node key.
NodeKey key.NodePublic
// GenesisAUM is the initial (genesis) AUM that the node generated
// to bootstrap tailnet key authority state.
GenesisAUM tkatype.MarshaledAUM
}
// TKASignInfo describes information about an existing node that needs
// to be signed into a node-key signature.
type TKASignInfo struct {
// NodeID is the ID of the node which needs a signature. It must
// correspond to NodePublic.
NodeID NodeID
// NodePublic is the node (Wireguard) public key which is being
// signed.
NodePublic key.NodePublic
// RotationPubkey specifies the public key which may sign
// a NodeKeySignature (NKS), which rotates the node key.
//
// This is necessary so the node can rotate its node-key without
// talking to a node which holds a trusted network-lock key.
// It does this by nesting the original NKS in a 'rotation' NKS,
// which it then signs with the key corresponding to RotationPubkey.
//
// This field expects a raw ed25519 public key.
RotationPubkey []byte
}
// TKAInitBeginResponse is the JSON response from a /tka/init/begin RPC.
// This structure describes node information which must be signed to
// complete initialization of the tailnets' key authority.
type TKAInitBeginResponse struct {
// NeedSignatures specify information about the nodes in your tailnet
// which need initial signatures to function once the tailnet key
// authority is in use. The generated signatures should then be
// submitted in a /tka/init/finish RPC.
NeedSignatures []TKASignInfo
}
// TKAInitFinishRequest is the JSON request of a /tka/init/finish RPC.
// This RPC finalizes initialization of the tailnet key authority
// by submitting node-key signatures for all existing nodes.
type TKAInitFinishRequest struct {
// Version is the client's capabilities.
Version CapabilityVersion
// NodeKey is the client's current node key.
NodeKey key.NodePublic
// Signatures are serialized tka.NodeKeySignatures for all nodes
// in the tailnet.
Signatures map[NodeID]tkatype.MarshaledSignature
// SupportDisablement is a disablement secret for Tailscale support.
// This is only generated if --gen-disablement-for-support is specified
// in an invocation to 'tailscale lock init'.
SupportDisablement []byte `json:",omitempty"`
}
// TKAInitFinishResponse is the JSON response from a /tka/init/finish RPC.
// This schema describes the successful enablement of the tailnet's
// key authority.
type TKAInitFinishResponse struct {
// Nothing. (yet?)
}
// TKAInfo encodes the control plane's view of tailnet key authority (TKA)
// state. This information is transmitted as part of the MapResponse.
type TKAInfo struct {
// Head describes the hash of the latest AUM applied to the authority.
// Head is encoded as tka.AUMHash.MarshalText.
//
// If the Head state differs to that known locally, the node should perform
// synchronization via a separate RPC.
Head string `json:",omitempty"`
// Disabled indicates the control plane believes TKA should be disabled,
// and the node should reach out to fetch a disablement
// secret. If the disablement secret verifies, then the node should then
// disable TKA locally.
// This field exists to disambiguate a nil TKAInfo in a delta mapresponse
// from a nil TKAInfo indicating TKA should be disabled.
Disabled bool `json:",omitempty"`
}
// TKABootstrapRequest is sent by a node to get information necessary for
// enabling or disabling the tailnet key authority.
type TKABootstrapRequest struct {
// Version is the client's capabilities.
Version CapabilityVersion
// NodeKey is the client's current node key.
NodeKey key.NodePublic
// Head represents the node's head AUMHash (tka.Authority.Head), if
// network lock is enabled.
Head string
}
// TKABootstrapResponse encodes values necessary to enable or disable
// the tailnet key authority (TKA).
type TKABootstrapResponse struct {
// GenesisAUM returns the initial AUM necessary to initialize TKA.
GenesisAUM tkatype.MarshaledAUM `json:",omitempty"`
// DisablementSecret encodes a secret necessary to disable TKA.
DisablementSecret []byte `json:",omitempty"`
}
// TKASyncOfferRequest encodes a request to synchronize tailnet key authority
// state (TKA). Values of type tka.AUMHash are encoded as strings in their
// MarshalText form.
type TKASyncOfferRequest struct {
// Version is the client's capabilities.
Version CapabilityVersion
// NodeKey is the client's current node key.
NodeKey key.NodePublic
// Head represents the node's head AUMHash (tka.Authority.Head). This
// corresponds to tka.SyncOffer.Head.
Head string
// Ancestors represents a selection of ancestor AUMHash values ascending
// from the current head. This corresponds to tka.SyncOffer.Ancestors.
Ancestors []string
}
// TKASyncOfferResponse encodes a response in synchronizing a node's
// tailnet key authority state. Values of type tka.AUMHash are encoded as
// strings in their MarshalText form.
type TKASyncOfferResponse struct {
// Head represents the control plane's head AUMHash (tka.Authority.Head).
// This corresponds to tka.SyncOffer.Head.
Head string
// Ancestors represents a selection of ancestor AUMHash values ascending
// from the control plane's head. This corresponds to
// tka.SyncOffer.Ancestors.
Ancestors []string
// MissingAUMs encodes AUMs that the control plane believes the node
// is missing.
MissingAUMs []tkatype.MarshaledAUM
}
// TKASyncSendRequest encodes AUMs that a node believes the control plane
// is missing, and notifies control of its local TKA state (specifically
// the head hash).
type TKASyncSendRequest struct {
// Version is the client's capabilities.
Version CapabilityVersion
// NodeKey is the client's current node key.
NodeKey key.NodePublic
// Head represents the node's head AUMHash (tka.Authority.Head) after
// applying any AUMs from the sync-offer response.
// It is encoded as tka.AUMHash.MarshalText.
Head string
// MissingAUMs encodes AUMs that the node believes the control plane
// is missing.
MissingAUMs []tkatype.MarshaledAUM
// Interactive is true if additional error checking should be performed as
// the request is on behalf of an interactive operation (e.g., an
// administrator publishing new changes) as opposed to an automatic
// synchronization that may be reporting lost data.
Interactive bool
}
// TKASyncSendResponse encodes the control plane's response to a node
// submitting AUMs during AUM synchronization.
type TKASyncSendResponse struct {
// Head represents the control plane's head AUMHash (tka.Authority.Head),
// after applying the missing AUMs.
Head string
}
// TKADisableRequest disables network-lock across the tailnet using the
// provided disablement secret.
//
// This is the request schema for a /tka/disable noise RPC.
type TKADisableRequest struct {
// Version is the client's capabilities.
Version CapabilityVersion
// NodeKey is the client's current node key.
NodeKey key.NodePublic
// Head represents the node's head AUMHash (tka.Authority.Head).
// It is encoded as tka.AUMHash.MarshalText.
Head string
// DisablementSecret encodes the secret necessary to disable TKA.
DisablementSecret []byte
}
// TKADisableResponse is the JSON response from a /tka/disable RPC.
// This schema describes the successful disablement of the tailnet's
// key authority.
type TKADisableResponse struct {
// Nothing. (yet?)
}
// TKASubmitSignatureRequest transmits a node-key signature to the control plane.
//
// This is the request schema for a /tka/sign noise RPC.
type TKASubmitSignatureRequest struct {
// Version is the client's capabilities.
Version CapabilityVersion
// NodeKey is the client's current node key. The node-key which
// is being signed is embedded in Signature.
NodeKey key.NodePublic
// Signature encodes the node-key signature being submitted.
Signature tkatype.MarshaledSignature
}
// TKASubmitSignatureResponse is the JSON response from a /tka/sign RPC.
type TKASubmitSignatureResponse struct {
// Nothing. (yet?)
}
// TKASignaturesUsingKeyRequest asks the control plane for
// all signatures which are signed by the provided keyID.
//
// This is the request schema for a /tka/affected-sigs RPC.
type TKASignaturesUsingKeyRequest struct {
// Version is the client's capabilities.
Version CapabilityVersion
// NodeKey is the client's current node key.
NodeKey key.NodePublic
// KeyID is the key we are querying using.
KeyID tkatype.KeyID
}
// TKASignaturesUsingKeyResponse is the JSON response to
// a /tka/affected-sigs RPC.
//
// It enumerates all signatures which are signed by the
// queried keyID.
type TKASignaturesUsingKeyResponse struct {
Signatures []tkatype.MarshaledSignature
}