mirror of
https://github.com/hanzoai/forge.git
synced 2026-10-30 15:00:39 +00:00
Source files keep their SPDX-License-Identifier and Hanzo copyright line; the Gitea, Gogs and LFS Test Server copyrights they used to repeat now live once in NOTICE, alongside LICENSE. The header lint accepts any copyright line above the SPDX line, so it no longer demands an upstream one. Co-authored-by: Hanzo Dev <[email protected]>
85 lines
2.3 KiB
Go
85 lines
2.3 KiB
Go
// Copyright 2026 Hanzo AI, Inc. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package cmd
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/hanzoai/git/modules/log"
|
|
"github.com/hanzoai/git/modules/private"
|
|
|
|
"github.com/urfave/cli/v3"
|
|
)
|
|
|
|
// NewKeysCommand returns the internal SSH key lookup sub-command.
|
|
func NewKeysCommand() *cli.Command {
|
|
return &cli.Command{
|
|
Name: "keys",
|
|
Usage: "(internal) Should only be called by SSH server",
|
|
Hidden: true, // internal commands shouldn't be visible
|
|
Description: "Queries the Hanzo Git database to get the authorized command for a given ssh key fingerprint",
|
|
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
|
Action: runKeys,
|
|
Flags: []cli.Flag{
|
|
&cli.StringFlag{
|
|
Name: "expected",
|
|
Aliases: []string{"e"},
|
|
Value: "git",
|
|
Usage: "Expected user for whom provide key commands",
|
|
},
|
|
&cli.StringFlag{
|
|
Name: "username",
|
|
Aliases: []string{"u"},
|
|
Value: "",
|
|
Usage: "Username trying to log in by SSH",
|
|
},
|
|
&cli.StringFlag{
|
|
Name: "type",
|
|
Aliases: []string{"t"},
|
|
Value: "",
|
|
Usage: "Type of the SSH key provided to the SSH Server (requires content to be provided too)",
|
|
},
|
|
&cli.StringFlag{
|
|
Name: "content",
|
|
Aliases: []string{"k"},
|
|
Value: "",
|
|
Usage: "Base64 encoded content of the SSH key provided to the SSH Server (requires type to be provided too)",
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func runKeys(ctx context.Context, c *cli.Command) error {
|
|
if !c.IsSet("username") {
|
|
return errors.New("No username provided")
|
|
}
|
|
// Check username matches the expected username
|
|
if strings.TrimSpace(c.String("username")) != strings.TrimSpace(c.String("expected")) {
|
|
return nil
|
|
}
|
|
|
|
content := ""
|
|
|
|
if c.IsSet("type") && c.IsSet("content") {
|
|
content = fmt.Sprintf("%s %s", strings.TrimSpace(c.String("type")), strings.TrimSpace(c.String("content")))
|
|
}
|
|
|
|
if content == "" {
|
|
return errors.New("No key type and content provided")
|
|
}
|
|
|
|
setup(ctx, c.Bool("debug"))
|
|
|
|
authorizedString, extra := private.AuthorizedPublicKeyByContent(ctx, content)
|
|
// do not use handleCliResponseExtra or cli.NewExitError, if it exists immediately, it breaks some tests like Test_CmdKeys
|
|
if extra.Error != nil {
|
|
return extra.Error
|
|
}
|
|
_, _ = fmt.Fprintln(c.Root().Writer, strings.TrimSpace(authorizedString.Text))
|
|
return nil
|
|
}
|