Documentation
¶
Overview ¶
Package nodeidentity owns the installation-level identity of a Tako node.
Installation identity is deliberately separate from takod's mutable project/environment metadata. It is created only by an explicit platform bootstrap or enrollment operation and is never writable through the takod runtime API.
Index ¶
- Constants
- func AcquireInventoryMutationLock(path string) (func(), error)
- func Create(path string, installation Installation) error
- func CreateInventory(path string, inventory ClusterInventory) error
- func DeploymentDenyPath(inventoryPath string) string
- func MeshCredentialID(publicKey string) (string, error)
- func OperationHolderTokenHash(holderToken string) (string, error)
- func ReplaceInventory(path string, inventory ClusterInventory) error
- func SignInventorySnapshot(snapshot *SignedInventorySnapshot, controller *Installation) error
- func SignOperationFence(fence *OperationFence, installation *Installation) error
- func ValidateAllocationPublicKey(publicKeyEncoded string) error
- func ValidateClusterID(value string) error
- func ValidateMeshPublicKey(value string) error
- func ValidateNodeID(value string) error
- func VerifyActiveAllocationOrigin(allocation ActiveAllocation, publicKey string) error
- func VerifyAllocationSignature(publicKeyEncoded string, message []byte, signatureEncoded string) error
- func VerifyInventorySnapshot(snapshot SignedInventorySnapshot, controllerPublicKey string, now time.Time) error
- func VerifyOperationFence(fence OperationFence, controllerPublicKey string, now time.Time) error
- func VerifyUpgradeContract(identityPath string, inventoryPath string, contract UpgradeContract) error
- func WriteLocalBinding(path string, binding LocalBinding) error
- type ActiveAllocation
- type ClusterInventory
- type Identity
- type Installation
- type InventoryNode
- type LocalBinding
- type NodeTombstone
- type OperationFence
- type Reference
- type SignedInventorySnapshot
- type UpgradeContract
Constants ¶
const ( APIVersion = "tako.io/v1" Kind = "InstallationIdentity" Capability = "node.identity-v1" DefaultPath = "/etc/tako/identity.json" RoleControlPlane = "control-plane" RoleWorker = "worker" RoleEdge = "edge" RoleBuilder = "builder" )
const ( InventoryAPIVersion = "tako.io/v1" InventoryKind = "ClusterInventory" DefaultInventoryPath = "/etc/tako/cluster-inventory.json" // DeploymentDenyFile is a durable, node-local safety latch. Lifecycle // commands set it on the target before committing a transition away from // schedulable, so a controller crash cannot leave a stale worker accepting // workload mutations indefinitely. DeploymentDenyFile = "deployment-denied" NodeLifecycleJoining = "joining" NodeLifecycleReady = "ready" NodeLifecycleSchedulable = "schedulable" NodeLifecycleCordoned = "cordoned" NodeLifecycleDraining = "draining" MeshCredentialActive = "active" MeshCredentialRevoked = "revoked" )
const ( LocalBindingKind = "LocalNodeBinding" DefaultLocalBindingPath = "/etc/tako/local-node.json" )
const OperationFenceKind = "ControllerOperationFence"
const SignedInventoryKind = "SignedClusterInventory"
Variables ¶
This section is empty.
Functions ¶
func AcquireInventoryMutationLock ¶
AcquireInventoryMutationLock serializes protected inventory publication with consumers that must validate and act on one exact inventory inode.
func Create ¶
func Create(path string, installation Installation) error
Create atomically publishes identity at path with mode 0600. Its protected parent directory must already exist. Create refuses to overwrite any existing path, including a symlink, so enrollment cannot silently replace a node's authority.
func CreateInventory ¶
func CreateInventory(path string, inventory ClusterInventory) error
func DeploymentDenyPath ¶
func MeshCredentialID ¶
func ReplaceInventory ¶
func ReplaceInventory(path string, inventory ClusterInventory) error
ReplaceInventory atomically publishes a new controller snapshot in the already protected inventory directory. It validates the complete snapshot before replacing the previous inode.
func SignInventorySnapshot ¶
func SignInventorySnapshot(snapshot *SignedInventorySnapshot, controller *Installation) error
func SignOperationFence ¶
func SignOperationFence(fence *OperationFence, installation *Installation) error
func ValidateClusterID ¶
ValidateClusterID checks the serialized cluster identity format.
func ValidateMeshPublicKey ¶
ValidateMeshPublicKey accepts the canonical WireGuard key representation: base64 of exactly 32 non-zero Curve25519 public-key bytes.
func ValidateNodeID ¶
ValidateNodeID checks the serialized node identity format.
func VerifyActiveAllocationOrigin ¶
func VerifyActiveAllocationOrigin(allocation ActiveAllocation, publicKey string) error
VerifyActiveAllocationOrigin proves that the exact durable allocation was emitted by the enrolled worker. Controller authorization is a separate step represented by AuthorizedAt and inventory publication.
func VerifyInventorySnapshot ¶
func VerifyInventorySnapshot(snapshot SignedInventorySnapshot, controllerPublicKey string, now time.Time) error
func VerifyOperationFence ¶
func VerifyOperationFence(fence OperationFence, controllerPublicKey string, now time.Time) error
func VerifyUpgradeContract ¶
func VerifyUpgradeContract(identityPath string, inventoryPath string, contract UpgradeContract) error
VerifyUpgradeContract reopens the protected identity and inventory and proves they still match the last takod attestation. Call it from the staged candidate immediately before publishing that candidate.
func WriteLocalBinding ¶
func WriteLocalBinding(path string, binding LocalBinding) error
Types ¶
type ActiveAllocation ¶
type ActiveAllocation struct {
Kind string `json:"kind"`
Project string `json:"project"`
Environment string `json:"environment"`
Service string `json:"service"`
Revision string `json:"revision,omitempty"`
Slot int `json:"slot"`
HostIP string `json:"hostIp"`
HostPort int `json:"hostPort"`
ContainerPort int `json:"containerPort"`
Key string `json:"key"`
ClusterID string `json:"clusterId"`
NodeID string `json:"nodeId"`
Generation uint64 `json:"generation"`
IssuedAt time.Time `json:"issuedAt"`
OperationID string `json:"operationId,omitempty"`
FenceToken uint64 `json:"fenceToken,omitempty"`
Signature string `json:"signature"`
AuthorizedAt time.Time `json:"authorizedAt"`
}
ActiveAllocation is the exact node-signed allocation generation that the single controller currently authorizes for routing. Omission is revocation.
type ClusterInventory ¶
type ClusterInventory struct {
APIVersion string `json:"apiVersion"`
Kind string `json:"kind"`
ClusterID string `json:"clusterId"`
Generation uint64 `json:"generation,omitempty"`
AllocationGeneration uint64 `json:"allocationGeneration,omitempty"`
ControllerNodeID string `json:"controllerNodeId,omitempty"`
MeshCIDR string `json:"meshCidr,omitempty"`
UpdatedAt time.Time `json:"updatedAt,omitempty"`
Nodes []InventoryNode `json:"nodes"`
Tombstones []NodeTombstone `json:"tombstones,omitempty"`
ActiveAllocations []ActiveAllocation `json:"activeAllocations,omitempty"`
}
ClusterInventory is a controller-published, read-only trust snapshot. Join token material and private credentials never appear here.
func ReadInventory ¶
func ReadInventory(path string) (*ClusterInventory, error)
func ReadInventoryOptional ¶
func ReadInventoryOptional(path string) (*ClusterInventory, error)
func (ClusterInventory) Allocation ¶
func (i ClusterInventory) Allocation(nodeID, key string, generation uint64) (ActiveAllocation, bool)
func (ClusterInventory) IsTombstoned ¶
func (i ClusterInventory) IsTombstoned(nodeID string) bool
func (ClusterInventory) Node ¶
func (i ClusterInventory) Node(nodeID string) (InventoryNode, bool)
func (ClusterInventory) Validate ¶
func (i ClusterInventory) Validate() error
type Identity ¶
type Identity struct {
APIVersion string `json:"apiVersion"`
Kind string `json:"kind"`
ClusterID string `json:"clusterId"`
NodeID string `json:"nodeId"`
NodeName string `json:"nodeName"`
CreatedAt time.Time `json:"createdAt"`
AllocationPublicKey string `json:"allocationPublicKey,omitempty"`
}
Identity is the immutable, installation-level identity of one Tako node. ClusterID and NodeID are UUIDs created during explicit enrollment. Runtime role assignments deliberately live outside this value so roles can move without changing node identity.
func (Identity) Matches ¶
Matches reports whether the immutable IDs identify the expected cluster member. Node names and IP addresses are intentionally not authority.
func (Identity) MatchesReference ¶
MatchesReference reports whether identity is the enrolled cluster member.
type Installation ¶
type Installation struct {
Identity
EnrollmentRoles []string `json:"roles"`
AllocationPrivateKey string `json:"allocationPrivateKey,omitempty"`
}
Installation is the create-once identity document. EnrollmentRoles record the roles requested at bootstrap/enrollment time; they are an audit fact, not the mutable current-role assignment introduced by the control plane.
func New ¶
func New(clusterID string, nodeID string, nodeName string, roles []string, now time.Time) (*Installation, error)
New creates a validated in-memory identity. An empty clusterID or nodeID is generated as a UUIDv4. Persist it with Create, which refuses replacement.
func Read ¶
func Read(path string) (*Installation, error)
Read validates and returns the installation identity at path. Symlinks, non-regular files, and group/world-accessible files are rejected.
func ReadOptional ¶
func ReadOptional(path string) (*Installation, error)
ReadOptional returns nil when no identity has been enrolled.
func (Installation) HasEnrollmentRole ¶
func (i Installation) HasEnrollmentRole(role string) bool
HasEnrollmentRole reports whether bootstrap/enrollment declared role.
func (Installation) Matches ¶
func (i Installation) Matches(clusterID string, nodeID string) bool
Matches reports whether the installation contains the expected identity.
func (Installation) SignAllocation ¶
func (i Installation) SignAllocation(message []byte) (string, error)
func (Installation) Validate ¶
func (i Installation) Validate() error
Validate checks the complete persisted installation contract.
type InventoryNode ¶
type InventoryNode struct {
NodeID string `json:"nodeId"`
NodeName string `json:"nodeName,omitempty"`
Lifecycle string `json:"lifecycle,omitempty"`
Roles []string `json:"roles,omitempty"`
Schedulable bool `json:"schedulable"`
MeshIP string `json:"meshIp,omitempty"`
MeshEndpoint string `json:"meshEndpoint,omitempty"`
MeshCredentialID string `json:"meshCredentialId,omitempty"`
MeshPublicKey string `json:"meshPublicKey,omitempty"`
MeshCredentialStatus string `json:"meshCredentialStatus,omitempty"`
SSHHost string `json:"sshHost,omitempty"`
SSHPort int `json:"sshPort,omitempty"`
SSHUser string `json:"sshUser,omitempty"`
SSHHostKeyType string `json:"sshHostKeyType,omitempty"`
SSHHostKey string `json:"sshHostKey,omitempty"`
SSHHostKeyFingerprint string `json:"sshHostKeyFingerprint,omitempty"`
AllocationPublicKey string `json:"allocationPublicKey"`
JoinedAt time.Time `json:"joinedAt,omitempty"`
UpdatedAt time.Time `json:"updatedAt,omitempty"`
}
type LocalBinding ¶
type LocalBinding struct {
APIVersion string `json:"apiVersion"`
Kind string `json:"kind"`
ClusterID string `json:"clusterId"`
NodeID string `json:"nodeId"`
NodeName string `json:"nodeName"`
WorkerUID int `json:"workerUid,omitempty"`
}
LocalBinding is the public, integrity-protected subset of installation identity needed by an unprivileged local operator. It contains no private keys or bearer credentials.
func ReadLocalBinding ¶
func ReadLocalBinding(path string) (*LocalBinding, error)
func (LocalBinding) Validate ¶
func (b LocalBinding) Validate() error
type NodeTombstone ¶
type NodeTombstone struct {
NodeID string `json:"nodeId"`
NodeName string `json:"nodeName,omitempty"`
RemovedAt time.Time `json:"removedAt"`
RemovedGeneration uint64 `json:"removedGeneration"`
RevokedMeshCredentialID string `json:"revokedMeshCredentialId,omitempty"`
RevokedMeshPublicKey string `json:"revokedMeshPublicKey,omitempty"`
AllocationKeyFingerprint string `json:"allocationKeyFingerprint,omitempty"`
}
type OperationFence ¶
type OperationFence struct {
Kind string `json:"kind"`
ClusterID string `json:"clusterId"`
ControllerNodeID string `json:"controllerNodeId"`
MembershipGeneration uint64 `json:"membershipGeneration"`
Project string `json:"project"`
Environment string `json:"environment"`
OperationID string `json:"operationId"`
Operation string `json:"operation"`
Token uint64 `json:"token"`
HolderTokenHash string `json:"holderTokenHash"`
TargetNodeIDs []string `json:"targetNodeIds"`
IssuedAt time.Time `json:"issuedAt"`
ExpiresAt time.Time `json:"expiresAt"`
Signature string `json:"signature"`
}
OperationFence is a controller-signed, monotonically fenced mutation grant. Workers accept it only after the controller has explicitly activated the exact token for that node. The token binds one project/environment operation to one membership generation and an explicit target set.
func (OperationFence) Targets ¶
func (f OperationFence) Targets(nodeID string) bool
type Reference ¶
type Reference struct {
ClusterID string `json:"clusterId" yaml:"clusterId"`
NodeID string `json:"nodeId" yaml:"nodeId"`
}
Reference identifies an enrolled cluster member without carrying mutable names, addresses, or roles.
type SignedInventorySnapshot ¶
type SignedInventorySnapshot struct {
Kind string `json:"kind"`
Inventory ClusterInventory `json:"inventory"`
IssuedAt time.Time `json:"issuedAt"`
Signature string `json:"signature"`
}
SignedInventorySnapshot lets the controller publish a newer trust snapshot to only the nodes an operation actually targets. Nodes verify it against their already trusted controller key and reject generation rollback.
type UpgradeContract ¶
type UpgradeContract struct {
ClusterID string `json:"clusterId"`
NodeID string `json:"nodeId"`
MembershipGeneration uint64 `json:"membershipGeneration"`
Lifecycle string `json:"lifecycle"`
Roles []string `json:"roles"`
}
UpgradeContract binds privileged binary publication to the exact protected identity and inventory generation most recently attested over takod.
func (UpgradeContract) Validate ¶
func (c UpgradeContract) Validate() error