Skip to content

Commit 5142ce1

Browse files
committed
Autodetermine if work-path needs to be specified in SSH authorized_keys
If a user's `app.ini` contains a `APP_DATA_PATH` which refers to a non-absolute path then `gitea serv` etc. become dependent on the `AppWorkPath`. `gitea serv` may then require `--work-path` to be set in the `authorized_keys` if the `AppWorkPath` determined by `gitea web` and `gitea serv` are different. This would occur if `GITEA_WORK_DIR` is set, `--work-path` is used to run `gitea web` or if the AppPath cannot be determined at start-up. This PR adds some code to attempt to automatically determine if this is necessary and adds some documentation to suggest adding `--work-path` to the template. This should prevent SSH failures from happening as described in go-gitea#19317 Replace go-gitea#22754 Signed-off-by: Andrew Thornton <[email protected]>
1 parent 188c8c1 commit 5142ce1

File tree

4 files changed

+44
-21
lines changed

4 files changed

+44
-21
lines changed

docs/content/doc/advanced/config-cheat-sheet.en-us.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,9 @@ The following configuration set `Content-Type: application/vnd.android.package-a
338338
- `SSH_CREATE_AUTHORIZED_PRINCIPALS_FILE`: **false/true**: Gitea will create a authorized_principals file by default when it is not using the internal ssh server and `SSH_AUTHORIZED_PRINCIPALS_ALLOW` is not `off`.
339339
- `SSH_AUTHORIZED_PRINCIPALS_BACKUP`: **false/true**: Enable SSH Authorized Principals Backup when rewriting all keys, default is true if `SSH_AUTHORIZED_PRINCIPALS_ALLOW` is not `off`.
340340
- `SSH_AUTHORIZED_KEYS_COMMAND_TEMPLATE`: **{{.AppPath}} --config={{.CustomConf}} serv key-{{.Key.ID}}**: Set the template for the command to passed on authorized keys. Possible keys are: AppPath, AppWorkPath, CustomConf, CustomPath, Key - where Key is a `models/asymkey.PublicKey` and the others are strings which are shellquoted.
341+
- Gitea will add `--work-path={{.AppWorkPath}}` to the default template
342+
if it determines that this is needed, however, you may need to add this explicitly
343+
to any non-default template if your `APP_DATA_PATH` is not an absolute path.
341344
- `SSH_SERVER_CIPHERS`: **[email protected], aes128-ctr, aes192-ctr, aes256-ctr, [email protected], [email protected]**: For the built-in SSH server, choose the ciphers to support for SSH connections, for system SSH this setting has no effect.
342345
- `SSH_SERVER_KEY_EXCHANGES`: **curve25519-sha256, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group14-sha256, diffie-hellman-group14-sha1**: For the built-in SSH server, choose the key exchange algorithms to support for SSH connections, for system SSH this setting has no effect.
343346
- `SSH_SERVER_MACS`: **[email protected], hmac-sha2-256, hmac-sha1**: For the built-in SSH server, choose the MACs to support for SSH connections, for system SSH this setting has no effect

modules/setting/server.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ var (
5353
AppSubURL string
5454
// AppDataPath is the default path for storing data.
5555
// It maps to ini:"APP_DATA_PATH" in [server] and defaults to AppWorkPath + "/data"
56-
AppDataPath string
56+
AppDataPath string
57+
AppDataPathDependentOnWorkPath bool // This is a helper marker used to inform if the AppDataPath is dependent on a user-provided or auto-determined work path
5758
// LocalURL is the url for locally running applications to contact Gitea. It always has a '/' suffix
5859
// It maps to ini:"LOCAL_ROOT_URL" in [server]
5960
LocalURL string
@@ -323,8 +324,14 @@ func loadServerFrom(rootCfg ConfigProvider) {
323324
}
324325
StaticRootPath = sec.Key("STATIC_ROOT_PATH").MustString(StaticRootPath)
325326
StaticCacheTime = sec.Key("STATIC_CACHE_TIME").MustDuration(6 * time.Hour)
326-
AppDataPath = sec.Key("APP_DATA_PATH").MustString(path.Join(AppWorkPath, "data"))
327+
AppDataPathDependentOnWorkPath = false
328+
AppDataPath = sec.Key("APP_DATA_PATH").MustString("")
329+
if AppDataPath == "" {
330+
AppDataPath = path.Join(AppWorkPath, "data")
331+
AppDataPathDependentOnWorkPath = appWorkPathIsNotDefault
332+
}
327333
if !filepath.IsAbs(AppDataPath) {
334+
AppDataPathDependentOnWorkPath = appWorkPathIsNotDefault
328335
log.Info("The provided APP_DATA_PATH: %s is not absolute - it will be made absolute against the work path: %s", AppDataPath, AppWorkPath)
329336
AppDataPath = filepath.ToSlash(filepath.Join(AppWorkPath, AppDataPath))
330337
}

modules/setting/setting.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ var (
3939
// If that is not set it is the default set here by the linker or failing that the directory of AppPath.
4040
//
4141
// AppWorkPath is used as the base path for several other paths.
42-
AppWorkPath string
42+
AppWorkPath string
43+
appWorkPathIsNotDefault bool
4344

4445
// Global setting objects
4546
CfgProvider ConfigProvider
@@ -82,8 +83,8 @@ func getAppPath() (string, error) {
8283

8384
func getWorkPath(appPath string) string {
8485
workPath := AppWorkPath
85-
8686
if giteaWorkPath, ok := os.LookupEnv("GITEA_WORK_DIR"); ok {
87+
appWorkPathIsNotDefault = true
8788
workPath = giteaWorkPath
8889
}
8990
if len(workPath) == 0 {
@@ -96,6 +97,7 @@ func getWorkPath(appPath string) string {
9697
}
9798
workPath = strings.ReplaceAll(workPath, "\\", "/")
9899
if !filepath.IsAbs(workPath) {
100+
appWorkPathIsNotDefault = true
99101
log.Info("Provided work path %s is not absolute - will be made absolute against the current working directory", workPath)
100102

101103
absPath, err := filepath.Abs(workPath)
@@ -159,10 +161,14 @@ func createPIDFile(pidPath string) {
159161

160162
// SetCustomPathAndConf will set CustomPath and CustomConf with reference to the
161163
// GITEA_CUSTOM environment variable and with provided overrides before stepping
162-
// back to the default
164+
// back to the defaultAppWorkPath =
163165
func SetCustomPathAndConf(providedCustom, providedConf, providedWorkPath string) {
164166
if len(providedWorkPath) != 0 {
165-
AppWorkPath = filepath.ToSlash(providedWorkPath)
167+
providedWorkPath = filepath.ToSlash(providedWorkPath)
168+
if providedWorkPath != AppWorkPath {
169+
appWorkPathIsNotDefault = true
170+
AppWorkPath = providedWorkPath
171+
}
166172
}
167173
if giteaCustom, ok := os.LookupEnv("GITEA_CUSTOM"); ok {
168174
CustomPath = giteaCustom

modules/setting/ssh.go

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ var SSH = struct {
3737
AuthorizedKeysBackup bool `ini:"SSH_AUTHORIZED_KEYS_BACKUP"`
3838
AuthorizedPrincipalsBackup bool `ini:"SSH_AUTHORIZED_PRINCIPALS_BACKUP"`
3939
AuthorizedKeysCommandTemplate string `ini:"SSH_AUTHORIZED_KEYS_COMMAND_TEMPLATE"`
40+
AuthorizedKeysCommandWorkPathTemplate string `ini:"-"`
4041
AuthorizedKeysCommandTemplateTemplate *template.Template `ini:"-"`
4142
MinimumKeySizeCheck bool `ini:"-"`
4243
MinimumKeySizes map[string]int `ini:"-"`
@@ -51,20 +52,21 @@ var SSH = struct {
5152
PerWriteTimeout time.Duration `ini:"SSH_PER_WRITE_TIMEOUT"`
5253
PerWritePerKbTimeout time.Duration `ini:"SSH_PER_WRITE_PER_KB_TIMEOUT"`
5354
}{
54-
Disabled: false,
55-
StartBuiltinServer: false,
56-
Domain: "",
57-
Port: 22,
58-
ServerCiphers: []string{"[email protected]", "aes128-ctr", "aes192-ctr", "aes256-ctr", "[email protected]", "[email protected]"},
59-
ServerKeyExchanges: []string{"curve25519-sha256", "ecdh-sha2-nistp256", "ecdh-sha2-nistp384", "ecdh-sha2-nistp521", "diffie-hellman-group14-sha256", "diffie-hellman-group14-sha1"},
60-
ServerMACs: []string{"[email protected]", "hmac-sha2-256", "hmac-sha1"},
61-
KeygenPath: "ssh-keygen",
62-
MinimumKeySizeCheck: true,
63-
MinimumKeySizes: map[string]int{"ed25519": 256, "ed25519-sk": 256, "ecdsa": 256, "ecdsa-sk": 256, "rsa": 2047},
64-
ServerHostKeys: []string{"ssh/gitea.rsa", "ssh/gogs.rsa"},
65-
AuthorizedKeysCommandTemplate: "{{.AppPath}} --config={{.CustomConf}} serv key-{{.Key.ID}}",
66-
PerWriteTimeout: PerWriteTimeout,
67-
PerWritePerKbTimeout: PerWritePerKbTimeout,
55+
Disabled: false,
56+
StartBuiltinServer: false,
57+
Domain: "",
58+
Port: 22,
59+
ServerCiphers: []string{"[email protected]", "aes128-ctr", "aes192-ctr", "aes256-ctr", "[email protected]", "[email protected]"},
60+
ServerKeyExchanges: []string{"curve25519-sha256", "ecdh-sha2-nistp256", "ecdh-sha2-nistp384", "ecdh-sha2-nistp521", "diffie-hellman-group14-sha256", "diffie-hellman-group14-sha1"},
61+
ServerMACs: []string{"[email protected]", "hmac-sha2-256", "hmac-sha1"},
62+
KeygenPath: "ssh-keygen",
63+
MinimumKeySizeCheck: true,
64+
MinimumKeySizes: map[string]int{"ed25519": 256, "ed25519-sk": 256, "ecdsa": 256, "ecdsa-sk": 256, "rsa": 2047},
65+
ServerHostKeys: []string{"ssh/gitea.rsa", "ssh/gogs.rsa"},
66+
AuthorizedKeysCommandTemplate: "{{.AppPath}} --config={{.CustomConf}} serv key-{{.Key.ID}}",
67+
AuthorizedKeysCommandWorkPathTemplate: "{{.AppPath}} --config={{.CustomConf}} --work-path={{.AppWorkPath}} serv key-{{.Key.ID}}",
68+
PerWriteTimeout: PerWriteTimeout,
69+
PerWritePerKbTimeout: PerWritePerKbTimeout,
6870
}
6971

7072
func parseAuthorizedPrincipalsAllow(values []string) ([]string, bool) {
@@ -184,7 +186,12 @@ func loadSSHFrom(rootCfg ConfigProvider) {
184186
}
185187

186188
SSH.ExposeAnonymous = sec.Key("SSH_EXPOSE_ANONYMOUS").MustBool(false)
187-
SSH.AuthorizedKeysCommandTemplate = sec.Key("SSH_AUTHORIZED_KEYS_COMMAND_TEMPLATE").MustString(SSH.AuthorizedKeysCommandTemplate)
189+
// Now if the AppData path is dependent on the work path we need to set a different default Template
190+
if AppDataPathDependentOnWorkPath {
191+
SSH.AuthorizedKeysCommandTemplate = sec.Key("SSH_AUTHORIZED_KEYS_COMMAND_TEMPLATE").MustString(SSH.AuthorizedKeysCommandWorkPathTemplate)
192+
} else {
193+
SSH.AuthorizedKeysCommandTemplate = sec.Key("SSH_AUTHORIZED_KEYS_COMMAND_TEMPLATE").MustString(SSH.AuthorizedKeysCommandTemplate)
194+
}
188195

189196
SSH.AuthorizedKeysCommandTemplateTemplate = template.Must(template.New("").Parse(SSH.AuthorizedKeysCommandTemplate))
190197

0 commit comments

Comments
 (0)