mirror of
https://github.com/go-gitea/gitea.git
synced 2026-06-10 05:20:28 +00:00
adds capabilities for gitea to generate ecdsa and ed25519 keys by default adds cli for built-in ssh key generation helpers closes: https://github.com/go-gitea/gitea/issues/33783 --------- Co-authored-by: Nicolas <bircni@icloud.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: Giteabot <teabot@gitea.io>
182 lines
4.4 KiB
Go
182 lines
4.4 KiB
Go
// Copyright 2016 The Gogs Authors. All rights reserved.
|
|
// Copyright 2016 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package cmd
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
|
|
"gitea.dev/modules/generate"
|
|
"gitea.dev/modules/ssh"
|
|
|
|
"github.com/mattn/go-isatty"
|
|
"github.com/urfave/cli/v3"
|
|
)
|
|
|
|
func newGenerateCommand() *cli.Command {
|
|
return &cli.Command{
|
|
Name: "generate",
|
|
Usage: "Generate Gitea's secrets/keys/tokens",
|
|
Commands: []*cli.Command{
|
|
newGenerateSecretCommand(),
|
|
newGenerateSSHCommand(),
|
|
},
|
|
}
|
|
}
|
|
|
|
func newGenerateSecretCommand() *cli.Command {
|
|
return &cli.Command{
|
|
Name: "secret",
|
|
Usage: "Generate a secret token",
|
|
Commands: []*cli.Command{
|
|
newGenerateInternalTokenCommand(),
|
|
newGenerateLfsJWTSecretCommand(),
|
|
newGenerateSecretKeyCommand(),
|
|
},
|
|
}
|
|
}
|
|
|
|
func newGenerateSSHCommand() *cli.Command {
|
|
return &cli.Command{
|
|
Name: "ssh",
|
|
Usage: "Generate ssh keys",
|
|
Commands: []*cli.Command{
|
|
newGenerateSSHKeyCommand(),
|
|
newGenerateSSHHostKeysCommand(),
|
|
},
|
|
}
|
|
}
|
|
|
|
func newGenerateInternalTokenCommand() *cli.Command {
|
|
return &cli.Command{
|
|
Name: "INTERNAL_TOKEN",
|
|
Usage: "Generate a new INTERNAL_TOKEN",
|
|
Action: runGenerateInternalToken,
|
|
}
|
|
}
|
|
|
|
func newGenerateLfsJWTSecretCommand() *cli.Command {
|
|
return &cli.Command{
|
|
Name: "JWT_SECRET",
|
|
Aliases: []string{"LFS_JWT_SECRET"},
|
|
Usage: "Generate a new JWT_SECRET",
|
|
Action: runGenerateLfsJwtSecret,
|
|
}
|
|
}
|
|
|
|
func newGenerateSecretKeyCommand() *cli.Command {
|
|
return &cli.Command{
|
|
Name: "SECRET_KEY",
|
|
Usage: "Generate a new SECRET_KEY",
|
|
Action: runGenerateSecretKey,
|
|
}
|
|
}
|
|
|
|
func newGenerateSSHKeyCommand() *cli.Command {
|
|
return &cli.Command{
|
|
Name: "key",
|
|
Usage: "Generate a new ssh key",
|
|
Flags: []cli.Flag{
|
|
&cli.IntFlag{Name: "bits", Aliases: []string{"b"}, Usage: "Number of bits in the key, ignored when key is ed25519"},
|
|
&cli.StringFlag{Name: "type", Aliases: []string{"t"}, Value: "ed25519", Usage: "Specifies the type of key to create."},
|
|
&cli.StringFlag{Name: "file", Aliases: []string{"f"}, Usage: "Specifies the path or base directory for the key file", Required: true},
|
|
},
|
|
Action: runGenerateKeyPair,
|
|
}
|
|
}
|
|
|
|
func newGenerateSSHHostKeysCommand() *cli.Command {
|
|
return &cli.Command{
|
|
Name: "host-keys",
|
|
Usage: "Generate host keys of all default key types (rsa, ecdsa, and ed25519) if they do not already exist.",
|
|
Flags: []cli.Flag{
|
|
&cli.StringFlag{Name: "dir", Aliases: []string{"d"}, Usage: "Specifies the base directory for the key files", Required: true},
|
|
},
|
|
Action: runGenerateHostKey,
|
|
}
|
|
}
|
|
|
|
func runGenerateInternalToken(_ context.Context, c *cli.Command) error {
|
|
internalToken, err := generate.NewInternalToken()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fmt.Printf("%s", internalToken)
|
|
|
|
if isatty.IsTerminal(os.Stdout.Fd()) {
|
|
fmt.Printf("\n")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func runGenerateLfsJwtSecret(_ context.Context, c *cli.Command) error {
|
|
_, jwtSecretBase64 := generate.NewJwtSecretWithBase64()
|
|
fmt.Printf("%s", jwtSecretBase64)
|
|
|
|
if isatty.IsTerminal(os.Stdout.Fd()) {
|
|
fmt.Printf("\n")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func runGenerateSecretKey(_ context.Context, c *cli.Command) error {
|
|
secretKey, err := generate.NewSecretKey()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// codeql[disable-next-line=go/clear-text-logging]
|
|
fmt.Printf("%s", secretKey)
|
|
|
|
if isatty.IsTerminal(os.Stdout.Fd()) {
|
|
fmt.Printf("\n")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func runGenerateHostKey(_ context.Context, c *cli.Command) error {
|
|
file := c.String("dir")
|
|
info, err := os.Stat(file)
|
|
if errors.Is(err, os.ErrNotExist) {
|
|
if err = os.MkdirAll(file, 0o644); err != nil {
|
|
return err
|
|
}
|
|
} else if err != nil {
|
|
return err
|
|
} else if !info.IsDir() {
|
|
return errors.New("file already exists and is not a directory")
|
|
}
|
|
fmt.Fprintf(c.Writer, "Generating host keys in %s\n", file)
|
|
_, err = ssh.InitDefaultHostKeys(file)
|
|
return err
|
|
}
|
|
|
|
func runGenerateKeyPair(_ context.Context, c *cli.Command) error {
|
|
file := c.String("file")
|
|
keyType := c.String("type")
|
|
|
|
fmt.Fprintf(c.Writer, "Generating public/private %s key pair.\n", keyType)
|
|
|
|
// Check if file exists to prevent overwriting
|
|
if _, err := os.Stat(file); err == nil {
|
|
if !confirm(c.Reader, c.Writer, "%s already exists.\nOverwrite (y/n)? ", file) {
|
|
fmt.Println("Aborting")
|
|
return nil
|
|
}
|
|
}
|
|
bits := c.Int("bits")
|
|
err := ssh.GenKeyPair(file, generate.SSHKeyType(keyType), bits)
|
|
if err == nil {
|
|
fmt.Printf("Your SSH key has been saved in %s\n", file)
|
|
}
|
|
return err
|
|
}
|