|
|
@ -1157,6 +1157,10 @@ type MapResponse struct {
|
|
|
|
// sees.
|
|
|
|
// sees.
|
|
|
|
Health []string `json:",omitempty"`
|
|
|
|
Health []string `json:",omitempty"`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// SSHPolicy, if non-nil, updates the SSH policy for how incoming
|
|
|
|
|
|
|
|
// SSH connections should be handled.
|
|
|
|
|
|
|
|
SSHPolicy *SSHPolicy `json:",omitempty"`
|
|
|
|
|
|
|
|
|
|
|
|
// Debug is normally nil, except for when the control server
|
|
|
|
// Debug is normally nil, except for when the control server
|
|
|
|
// is setting debug settings on a node.
|
|
|
|
// is setting debug settings on a node.
|
|
|
|
Debug *Debug `json:",omitempty"`
|
|
|
|
Debug *Debug `json:",omitempty"`
|
|
|
@ -1369,3 +1373,81 @@ type SetDNSRequest struct {
|
|
|
|
// Value is the value to add.
|
|
|
|
// Value is the value to add.
|
|
|
|
Value string
|
|
|
|
Value string
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// SSHPolicy is the policy for how to handle incoming SSH connections
|
|
|
|
|
|
|
|
// over Tailscale.
|
|
|
|
|
|
|
|
type SSHPolicy struct {
|
|
|
|
|
|
|
|
// Rules are the rules to process for an incoming SSH
|
|
|
|
|
|
|
|
// connection. The first matching rule takes its action and
|
|
|
|
|
|
|
|
// stops processing further rules.
|
|
|
|
|
|
|
|
Rules []*SSHRule `json:"rules"`
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// An SSH rule is a match predicate and associated action for an incoming SSH connection.
|
|
|
|
|
|
|
|
type SSHRule struct {
|
|
|
|
|
|
|
|
// RuleExpires, if non-nil, is when this rule expires.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// For example, a (principal,sshuser) tuple might be granted
|
|
|
|
|
|
|
|
// prompt-free SSH access for N minutes, so this rule would be
|
|
|
|
|
|
|
|
// before a expiration-free rule for the same principal that
|
|
|
|
|
|
|
|
// required an auth prompt. This permits the control plane to
|
|
|
|
|
|
|
|
// be out of the path for already-authorized SSH pairs.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Once a rule matches, the lifetime of any accepting connection
|
|
|
|
|
|
|
|
// is subject to the SSHAction.SessionExpires time, if any.
|
|
|
|
|
|
|
|
RuleExpires *time.Time `json:"ruleExpires,omitempty"`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Principals matches an incoming connection. If the connection
|
|
|
|
|
|
|
|
// matches anything in this list and also matches SSHUsers,
|
|
|
|
|
|
|
|
// then Action is applied.
|
|
|
|
|
|
|
|
Principals []*SSHPrincipal `json:"principals"`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// SSHUsers are the SSH users that this rule matches. It is a
|
|
|
|
|
|
|
|
// map from either ssh-user|"*" => local-user. The map must
|
|
|
|
|
|
|
|
// contain a key for either ssh-user or, as a fallback, "*" to
|
|
|
|
|
|
|
|
// match anything. If it does, the map entry's value is the
|
|
|
|
|
|
|
|
// actual user that's logged in.
|
|
|
|
|
|
|
|
SSHUsers map[string]string `json:"sshUsers"`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Action is the outcome to task.
|
|
|
|
|
|
|
|
// A nil or invalid action means to deny.
|
|
|
|
|
|
|
|
Action *SSHAction `json:"action"`
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// SSHPrincipal is either a particular node or a user on any node.
|
|
|
|
|
|
|
|
// At most one field should be non-zero specified.
|
|
|
|
|
|
|
|
type SSHPrincipal struct {
|
|
|
|
|
|
|
|
Node StableNodeID `json:"node,omitempty"`
|
|
|
|
|
|
|
|
NodeIP string `json:"nodeIP,omitempty"`
|
|
|
|
|
|
|
|
UserLogin string `json:"userLogin,omitempty"` // email-ish: foo@example.com, bar@github
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO(bradfitz): add StableUserID, once that exists
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// SSHAction is how to handle an incoming connection.
|
|
|
|
|
|
|
|
// At most one field should be non-zero.
|
|
|
|
|
|
|
|
type SSHAction struct {
|
|
|
|
|
|
|
|
// Message, if non-empty, is shown to the user before the
|
|
|
|
|
|
|
|
// action occurs.
|
|
|
|
|
|
|
|
Message string `json:"message,omitempty"`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Reject, if true, terminates the connection. This action
|
|
|
|
|
|
|
|
// has higher priority that Accept, if given.
|
|
|
|
|
|
|
|
// The reason this is exists is primarily so a response
|
|
|
|
|
|
|
|
// from HoldAndDelegate has a way to stop the poll.
|
|
|
|
|
|
|
|
Reject bool `json:"reject,omitempty"`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Accept, if true, accepts the connection immediately
|
|
|
|
|
|
|
|
// without further prompts.
|
|
|
|
|
|
|
|
Accept bool `json:"accept,omitempty"`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// SesssionExpires, if non-nil, is the time at which this
|
|
|
|
|
|
|
|
// session should forcefully terminate.
|
|
|
|
|
|
|
|
SesssionExpires *time.Time `json:"sessionExpires,omitempty"`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// HoldAndDelegate, if non-empty, is a URL that serves an outcome verdict.
|
|
|
|
|
|
|
|
// The connection will be accepted and will block until the
|
|
|
|
|
|
|
|
// provided long-polling URL serves a new SSHAction JSON
|
|
|
|
|
|
|
|
// value.
|
|
|
|
|
|
|
|
HoldAndDelegate string `json:"holdAndDelegate,omitempty"`
|
|
|
|
|
|
|
|
}
|
|
|
|