Documentation
¶
Overview ¶
Package access implements the business logic behind `nself access grant / revoke / list` — managing SSH public keys in the authorized_keys file of an already-deployed nself host. It never touches private key material: every entry point here accepts or produces public keys and fingerprints only.
Purpose: fill the gap where hcloud only injects SSH keys at server-creation time, leaving no CLI path to grant or revoke access on a running box without hand-editing authorized_keys over a raw ssh session. Inputs: a Transport (SSHTransport in production, LocalFileTransport in tests) plus a parsed PublicKey and request options. Outputs: GrantResult / RevokeResult / ListResult describing what changed, including the key fingerprint for verification. Constraints: idempotent grant, timestamped backup before every mutation, a lockout guard on revoke, and an audit line per mutation. See manager.go, transport.go, and audit.go for the pieces of that contract.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrLastKey = errors.New("refusing to remove the last remaining authorized key: this would lock out all SSH access to the host; pass --force to override")
ErrLastKey is returned by Revoke when removing the requested key would leave the host with zero authorized keys — the lockout failure mode this command exists to prevent.
Functions ¶
func SetAuditLogPathForTest ¶
func SetAuditLogPathForTest(path string) func()
SetAuditLogPathForTest redirects the audit log to path for the duration of a test and returns a restore function to call in a defer.
Types ¶
type Entry ¶
type Entry struct {
// User is the label identifying whose key this is (e.g. a teammate's
// name), not necessarily a Unix account — grant/revoke key entries by
// this label, independent of which OS account authorized_keys belongs to.
User string
Key PublicKey
// Sudo and Docker record the intended privilege level for this grant.
// They are audit/inventory metadata only: this package does not itself
// modify OS group membership. See the access wiki page for the reasoning.
Sudo bool
Docker bool
Expires *time.Time
Granted time.Time
}
Entry is one nself-managed authorized_keys line: a single public key granted to a named person, with optional privilege metadata and expiry.
func (Entry) Fingerprint ¶
Fingerprint is a convenience wrapper around Key.Fingerprint. A managed entry's key has already been validated once at grant time, so a parse error here (which should not happen) degrades to an empty string rather than panicking a caller that only wants a display value.
type GrantRequest ¶
type GrantRequest struct {
User string
Key PublicKey
Sudo bool
Docker bool
Expires *time.Time
DryRun bool
}
GrantRequest describes one `nself access grant` invocation.
type GrantResult ¶
GrantResult reports what Grant did or would do.
func Grant ¶
func Grant(ctx context.Context, t Transport, req GrantRequest) (GrantResult, error)
Grant adds or updates req.User's managed key on t. Re-granting the exact same key with the same --sudo/--docker/--expires for the same user is a no-op (AlreadyGranted=true) — it never duplicates a line. Granting a different key, or different metadata, for an existing user replaces that user's single managed line in place.
type ListResult ¶
ListResult reports every nself-managed entry found, plus a count of foreign (non-nself-managed) key lines sharing the file.
type LocalFileTransport ¶
type LocalFileTransport struct {
Path string
// contains filtered or unexported fields
}
LocalFileTransport implements Transport against a file on the local filesystem.
func NewLocalFileTransport ¶
func NewLocalFileTransport(path string) *LocalFileTransport
NewLocalFileTransport returns a Transport rooted at path.
func (*LocalFileTransport) Backup ¶
func (t *LocalFileTransport) Backup(ctx context.Context) (string, error)
Backup copies the current file to "<path>.bak.<UTC timestamp>" and returns that path, or "" if there was nothing to back up.
func (*LocalFileTransport) Describe ¶
func (t *LocalFileTransport) Describe() string
type PublicKey ¶
PublicKey is a parsed SSH public key: its algorithm identifier and the base64-encoded key blob. A PublicKey never carries private key material.
func LoadPublicKeyArg ¶
LoadPublicKeyArg resolves the `--key <pubkey|@file>` convention: a leading '@' means read the key from the given file path, otherwise arg is the key material itself.
func ParsePublicKey ¶
ParsePublicKey parses a single authorized_keys-style public key line ("<type> <base64> [comment...]"), ignoring any comment. It refuses input that looks like a private key without echoing that input anywhere, so a pasted private key is never reflected back to the terminal or a log line.
func (PublicKey) Fingerprint ¶
Fingerprint returns the key's fingerprint in the same format `ssh-keygen -lf` prints: "SHA256:<unpadded base64 of sha256(key blob)>".
type RevokeRequest ¶
RevokeRequest describes one `nself access revoke` invocation.
type RevokeResult ¶
RevokeResult reports what Revoke did or would do.
func Revoke ¶
func Revoke(ctx context.Context, t Transport, req RevokeRequest) (RevokeResult, error)
Revoke removes req.User's managed key from t. It refuses to proceed (ErrLastKey) when the target host would be left with zero authorized keys, unless req.Force is set.
type SSHTransport ¶
type SSHTransport struct {
// Host is "[user@]host" — the ssh connection target, e.g. "root@5.75.235.42".
Host string
// IdentityPath is the local private key used to authenticate the SSH
// connection (the operator's own key, distinct from any key being
// granted or revoked).
IdentityPath string
// RemotePath is the authorized_keys path on the remote host. Defaults to
// "~/.ssh/authorized_keys" (relative to whichever account Host connects
// as) when empty.
RemotePath string
}
SSHTransport implements Transport by running the ssh binary against a real host.
func (*SSHTransport) Backup ¶
func (t *SSHTransport) Backup(ctx context.Context) (string, error)
Backup copies the remote file to a timestamped sibling and returns that remote path, or "" if there was nothing to back up.
func (*SSHTransport) Describe ¶
func (t *SSHTransport) Describe() string
type Transport ¶
type Transport interface {
// Describe returns a short human-readable label for error messages and
// audit lines, e.g. "root@5.75.235.42" or a fixture's file path.
Describe() string
// Read returns the current authorized_keys content, or (nil, nil) if the
// file does not exist yet — a fresh host with no managed keys is not an
// error.
Read(ctx context.Context) ([]byte, error)
// Backup copies the current file to a timestamped sibling before any
// mutation and returns its path. If the file does not exist yet, Backup
// is a no-op that returns "".
Backup(ctx context.Context) (string, error)
// Write replaces the authorized_keys content and ensures the result is
// readable only by its owner (0600), matching the CLI's env-file
// permission rule.
Write(ctx context.Context, content []byte) error
}
Transport reads, backs up, and writes one remote (or fixture) authorized_keys file.