| @@ -27,10 +27,14 @@ func argsSet(c *cli.Context, args ...string) error { | |||
| } | |||
| func initDB() error { | |||
| return initDBDisableConsole(false) | |||
| } | |||
| func initDBDisableConsole(disableConsole bool) error { | |||
| setting.NewContext() | |||
| models.LoadConfigs() | |||
| setting.NewXORMLogService(false) | |||
| setting.NewXORMLogService(disableConsole) | |||
| if err := models.SetEngine(); err != nil { | |||
| return fmt.Errorf("models.SetEngine: %v", err) | |||
| } | |||
| @@ -0,0 +1,85 @@ | |||
| // Copyright 2018 The Gitea Authors. All rights reserved. | |||
| // Use of this source code is governed by a MIT-style | |||
| // license that can be found in the LICENSE file. | |||
| package cmd | |||
| import ( | |||
| "errors" | |||
| "fmt" | |||
| "strings" | |||
| "code.gitea.io/gitea/models" | |||
| "code.gitea.io/gitea/modules/setting" | |||
| "github.com/urfave/cli" | |||
| ) | |||
| // CmdKeys represents the available keys sub-command | |||
| var CmdKeys = cli.Command{ | |||
| Name: "keys", | |||
| Usage: "This command queries the Gitea database to get the authorized command for a given ssh key fingerprint", | |||
| Action: runKeys, | |||
| Flags: []cli.Flag{ | |||
| cli.StringFlag{ | |||
| Name: "expected, e", | |||
| Value: "git", | |||
| Usage: "Expected user for whom provide key commands", | |||
| }, | |||
| cli.StringFlag{ | |||
| Name: "username, u", | |||
| Value: "", | |||
| Usage: "Username trying to log in by SSH", | |||
| }, | |||
| cli.StringFlag{ | |||
| Name: "type, t", | |||
| Value: "", | |||
| Usage: "Type of the SSH key provided to the SSH Server (requires content to be provided too)", | |||
| }, | |||
| cli.StringFlag{ | |||
| Name: "content, k", | |||
| Value: "", | |||
| Usage: "Base64 encoded content of the SSH key provided to the SSH Server (requires type to be provided too)", | |||
| }, | |||
| cli.StringFlag{ | |||
| Name: "config, c", | |||
| Value: "custom/conf/app.ini", | |||
| Usage: "Custom configuration file path", | |||
| }, | |||
| }, | |||
| } | |||
| func runKeys(c *cli.Context) error { | |||
| if c.IsSet("config") { | |||
| setting.CustomConf = c.String("config") | |||
| } | |||
| 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") | |||
| } | |||
| if err := initDBDisableConsole(true); err != nil { | |||
| return err | |||
| } | |||
| publicKey, err := models.SearchPublicKeyByContent(content) | |||
| if err != nil { | |||
| return err | |||
| } | |||
| fmt.Println(publicKey.AuthorizedString()) | |||
| return nil | |||
| } | |||
| @@ -154,6 +154,9 @@ SSH_PORT = 22 | |||
| SSH_LISTEN_PORT = %(SSH_PORT)s | |||
| ; Root path of SSH directory, default is '~/.ssh', but you have to use '/home/git/.ssh'. | |||
| SSH_ROOT_PATH = | |||
| ; Gitea will create a authorized_keys file by default when it is not using the internal ssh server | |||
| ; If you intend to use the AuthorizedKeysCommand functionality then you should turn this off. | |||
| SSH_CREATE_AUTHORIZED_KEYS_FILE = true | |||
| ; For the built-in SSH server, choose the ciphers to support for SSH connections, | |||
| ; for system SSH this setting has no effect | |||
| SSH_SERVER_CIPHERS = aes128-ctr, aes192-ctr, aes256-ctr, aes128-gcm@openssh.com, arcfour256, arcfour128 | |||
| @@ -163,3 +163,24 @@ for automatic deployments. | |||
| - `gitea generate secret INTERNAL_TOKEN` | |||
| - `gitea generate secret LFS_JWT_SECRET` | |||
| - `gitea generate secret SECRET_KEY` | |||
| #### keys | |||
| Provides an SSHD AuthorizedKeysCommand. Needs to be configured in the sshd config file: | |||
| ```ini | |||
| ... | |||
| # The value of -e and the AuthorizedKeysCommandUser should match the | |||
| # username running gitea | |||
| AuthorizedKeysCommandUser git | |||
| AuthorizedKeysCommand /path/to/gitea keys -e git -u %u -t %t -k %k | |||
| ``` | |||
| The command will return the appropriate authorized_keys line for the | |||
| provided key. You should also set the value | |||
| `SSH_CREATE_AUTHORIZED_KEYS_FILE=false` in the `[server]` section of | |||
| `app.ini`. | |||
| NB: opensshd requires the gitea program to be owned by root and not | |||
| writable by group or others. The program must be specified by an absolute | |||
| path. | |||
| @@ -13,6 +13,7 @@ import ( | |||
| "code.gitea.io/gitea/cmd" | |||
| "code.gitea.io/gitea/modules/log" | |||
| "code.gitea.io/gitea/modules/setting" | |||
| // register supported doc types | |||
| _ "code.gitea.io/gitea/modules/markup/csv" | |||
| _ "code.gitea.io/gitea/modules/markup/markdown" | |||
| @@ -48,6 +49,7 @@ arguments - which can alternatively be run by running the subcommand web.` | |||
| cmd.CmdAdmin, | |||
| cmd.CmdGenerate, | |||
| cmd.CmdMigrate, | |||
| cmd.CmdKeys, | |||
| } | |||
| app.Flags = append(app.Flags, cmd.CmdWeb.Flags...) | |||
| app.Action = cmd.CmdWeb.Action | |||
| @@ -558,7 +558,7 @@ func DeletePublicKey(doer *User, id int64) (err error) { | |||
| // outside any session scope independently. | |||
| func RewriteAllPublicKeys() error { | |||
| //Don't rewrite key if internal server | |||
| if setting.SSH.StartBuiltinServer { | |||
| if setting.SSH.StartBuiltinServer || !setting.SSH.CreateAuthorizedKeysFile { | |||
| return nil | |||
| } | |||
| @@ -118,23 +118,24 @@ var ( | |||
| LetsEncryptEmail string | |||
| SSH = struct { | |||
| Disabled bool `ini:"DISABLE_SSH"` | |||
| StartBuiltinServer bool `ini:"START_SSH_SERVER"` | |||
| BuiltinServerUser string `ini:"BUILTIN_SSH_SERVER_USER"` | |||
| Domain string `ini:"SSH_DOMAIN"` | |||
| Port int `ini:"SSH_PORT"` | |||
| ListenHost string `ini:"SSH_LISTEN_HOST"` | |||
| ListenPort int `ini:"SSH_LISTEN_PORT"` | |||
| RootPath string `ini:"SSH_ROOT_PATH"` | |||
| ServerCiphers []string `ini:"SSH_SERVER_CIPHERS"` | |||
| ServerKeyExchanges []string `ini:"SSH_SERVER_KEY_EXCHANGES"` | |||
| ServerMACs []string `ini:"SSH_SERVER_MACS"` | |||
| KeyTestPath string `ini:"SSH_KEY_TEST_PATH"` | |||
| KeygenPath string `ini:"SSH_KEYGEN_PATH"` | |||
| AuthorizedKeysBackup bool `ini:"SSH_AUTHORIZED_KEYS_BACKUP"` | |||
| MinimumKeySizeCheck bool `ini:"-"` | |||
| MinimumKeySizes map[string]int `ini:"-"` | |||
| ExposeAnonymous bool `ini:"SSH_EXPOSE_ANONYMOUS"` | |||
| Disabled bool `ini:"DISABLE_SSH"` | |||
| StartBuiltinServer bool `ini:"START_SSH_SERVER"` | |||
| BuiltinServerUser string `ini:"BUILTIN_SSH_SERVER_USER"` | |||
| Domain string `ini:"SSH_DOMAIN"` | |||
| Port int `ini:"SSH_PORT"` | |||
| ListenHost string `ini:"SSH_LISTEN_HOST"` | |||
| ListenPort int `ini:"SSH_LISTEN_PORT"` | |||
| RootPath string `ini:"SSH_ROOT_PATH"` | |||
| ServerCiphers []string `ini:"SSH_SERVER_CIPHERS"` | |||
| ServerKeyExchanges []string `ini:"SSH_SERVER_KEY_EXCHANGES"` | |||
| ServerMACs []string `ini:"SSH_SERVER_MACS"` | |||
| KeyTestPath string `ini:"SSH_KEY_TEST_PATH"` | |||
| KeygenPath string `ini:"SSH_KEYGEN_PATH"` | |||
| AuthorizedKeysBackup bool `ini:"SSH_AUTHORIZED_KEYS_BACKUP"` | |||
| MinimumKeySizeCheck bool `ini:"-"` | |||
| MinimumKeySizes map[string]int `ini:"-"` | |||
| CreateAuthorizedKeysFile bool `ini:"SSH_CREATE_AUTHORIZED_KEYS_FILE"` | |||
| ExposeAnonymous bool `ini:"SSH_EXPOSE_ANONYMOUS"` | |||
| }{ | |||
| Disabled: false, | |||
| StartBuiltinServer: false, | |||
| @@ -863,6 +864,7 @@ func NewContext() { | |||
| } | |||
| } | |||
| SSH.AuthorizedKeysBackup = sec.Key("SSH_AUTHORIZED_KEYS_BACKUP").MustBool(true) | |||
| SSH.CreateAuthorizedKeysFile = sec.Key("SSH_CREATE_AUTHORIZED_KEYS_FILE").MustBool(true) | |||
| SSH.ExposeAnonymous = sec.Key("SSH_EXPOSE_ANONYMOUS").MustBool(false) | |||
| sec = Cfg.Section("server") | |||