mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-12-22 16:33:55 +01:00
AuthorizedKeysCommand should not query db directly (#9371)
* AuthorizedKeysCommand should not query db directly * Update routers/private/internal.go * Fix import order
This commit is contained in:
parent
1707f59966
commit
d1a49977b0
6 changed files with 93 additions and 50 deletions
10
cmd/keys.go
10
cmd/keys.go
|
@ -9,7 +9,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/modules/private"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
|
@ -62,14 +62,12 @@ func runKeys(c *cli.Context) error {
|
||||||
return errors.New("No key type and content provided")
|
return errors.New("No key type and content provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := initDBDisableConsole(true); err != nil {
|
setup("keys.log")
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
publicKey, err := models.SearchPublicKeyByContent(content)
|
authorizedString, err := private.AuthorizedPublicKeyByContent(content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Println(publicKey.AuthorizedString())
|
fmt.Println(strings.TrimSpace(authorizedString))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -281,6 +281,7 @@ provided key. You should also set the value
|
||||||
NB: opensshd requires the gitea program to be owned by root and not
|
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
|
writable by group or others. The program must be specified by an absolute
|
||||||
path.
|
path.
|
||||||
|
NB: Gitea must be running for this command to succeed.
|
||||||
|
|
||||||
#### migrate
|
#### migrate
|
||||||
Migrates the database. This command can be used to run other commands before starting the server for the first time.
|
Migrates the database. This command can be used to run other commands before starting the server for the first time.
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"flag"
|
"flag"
|
||||||
"io"
|
"io"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -18,8 +19,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_CmdKeys(t *testing.T) {
|
func Test_CmdKeys(t *testing.T) {
|
||||||
defer prepareTestEnv(t)()
|
onGiteaRun(t, func(*testing.T, *url.URL) {
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
args []string
|
args []string
|
||||||
|
@ -31,7 +31,7 @@ func Test_CmdKeys(t *testing.T) {
|
||||||
{"with_key",
|
{"with_key",
|
||||||
[]string{"keys", "-e", "git", "-u", "git", "-t", "ssh-rsa", "-k", "AAAAB3NzaC1yc2EAAAADAQABAAABgQDWVj0fQ5N8wNc0LVNA41wDLYJ89ZIbejrPfg/avyj3u/ZohAKsQclxG4Ju0VirduBFF9EOiuxoiFBRr3xRpqzpsZtnMPkWVWb+akZwBFAx8p+jKdy4QXR/SZqbVobrGwip2UjSrri1CtBxpJikojRIZfCnDaMOyd9Jp6KkujvniFzUWdLmCPxUE9zhTaPu0JsEP7MW0m6yx7ZUhHyfss+NtqmFTaDO+QlMR7L2QkDliN2Jl3Xa3PhuWnKJfWhdAq1Cw4oraKUOmIgXLkuiuxVQ6mD3AiFupkmfqdHq6h+uHHmyQqv3gU+/sD8GbGAhf6ftqhTsXjnv1Aj4R8NoDf9BS6KRkzkeun5UisSzgtfQzjOMEiJtmrep2ZQrMGahrXa+q4VKr0aKJfm+KlLfwm/JztfsBcqQWNcTURiCFqz+fgZw0Ey/de0eyMzldYTdXXNRYCKjs9bvBK+6SSXRM7AhftfQ0ZuoW5+gtinPrnmoOaSCEJbAiEiTO/BzOHgowiM="},
|
[]string{"keys", "-e", "git", "-u", "git", "-t", "ssh-rsa", "-k", "AAAAB3NzaC1yc2EAAAADAQABAAABgQDWVj0fQ5N8wNc0LVNA41wDLYJ89ZIbejrPfg/avyj3u/ZohAKsQclxG4Ju0VirduBFF9EOiuxoiFBRr3xRpqzpsZtnMPkWVWb+akZwBFAx8p+jKdy4QXR/SZqbVobrGwip2UjSrri1CtBxpJikojRIZfCnDaMOyd9Jp6KkujvniFzUWdLmCPxUE9zhTaPu0JsEP7MW0m6yx7ZUhHyfss+NtqmFTaDO+QlMR7L2QkDliN2Jl3Xa3PhuWnKJfWhdAq1Cw4oraKUOmIgXLkuiuxVQ6mD3AiFupkmfqdHq6h+uHHmyQqv3gU+/sD8GbGAhf6ftqhTsXjnv1Aj4R8NoDf9BS6KRkzkeun5UisSzgtfQzjOMEiJtmrep2ZQrMGahrXa+q4VKr0aKJfm+KlLfwm/JztfsBcqQWNcTURiCFqz+fgZw0Ey/de0eyMzldYTdXXNRYCKjs9bvBK+6SSXRM7AhftfQ0ZuoW5+gtinPrnmoOaSCEJbAiEiTO/BzOHgowiM="},
|
||||||
false,
|
false,
|
||||||
"# gitea public key\ncommand=\"" + setting.AppPath + " --config='" + setting.CustomConf + "' serv key-1\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDWVj0fQ5N8wNc0LVNA41wDLYJ89ZIbejrPfg/avyj3u/ZohAKsQclxG4Ju0VirduBFF9EOiuxoiFBRr3xRpqzpsZtnMPkWVWb+akZwBFAx8p+jKdy4QXR/SZqbVobrGwip2UjSrri1CtBxpJikojRIZfCnDaMOyd9Jp6KkujvniFzUWdLmCPxUE9zhTaPu0JsEP7MW0m6yx7ZUhHyfss+NtqmFTaDO+QlMR7L2QkDliN2Jl3Xa3PhuWnKJfWhdAq1Cw4oraKUOmIgXLkuiuxVQ6mD3AiFupkmfqdHq6h+uHHmyQqv3gU+/sD8GbGAhf6ftqhTsXjnv1Aj4R8NoDf9BS6KRkzkeun5UisSzgtfQzjOMEiJtmrep2ZQrMGahrXa+q4VKr0aKJfm+KlLfwm/JztfsBcqQWNcTURiCFqz+fgZw0Ey/de0eyMzldYTdXXNRYCKjs9bvBK+6SSXRM7AhftfQ0ZuoW5+gtinPrnmoOaSCEJbAiEiTO/BzOHgowiM= user2@localhost\n\n",
|
"# gitea public key\ncommand=\"" + setting.AppPath + " --config='" + setting.CustomConf + "' serv key-1\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDWVj0fQ5N8wNc0LVNA41wDLYJ89ZIbejrPfg/avyj3u/ZohAKsQclxG4Ju0VirduBFF9EOiuxoiFBRr3xRpqzpsZtnMPkWVWb+akZwBFAx8p+jKdy4QXR/SZqbVobrGwip2UjSrri1CtBxpJikojRIZfCnDaMOyd9Jp6KkujvniFzUWdLmCPxUE9zhTaPu0JsEP7MW0m6yx7ZUhHyfss+NtqmFTaDO+QlMR7L2QkDliN2Jl3Xa3PhuWnKJfWhdAq1Cw4oraKUOmIgXLkuiuxVQ6mD3AiFupkmfqdHq6h+uHHmyQqv3gU+/sD8GbGAhf6ftqhTsXjnv1Aj4R8NoDf9BS6KRkzkeun5UisSzgtfQzjOMEiJtmrep2ZQrMGahrXa+q4VKr0aKJfm+KlLfwm/JztfsBcqQWNcTURiCFqz+fgZw0Ey/de0eyMzldYTdXXNRYCKjs9bvBK+6SSXRM7AhftfQ0ZuoW5+gtinPrnmoOaSCEJbAiEiTO/BzOHgowiM= user2@localhost\n",
|
||||||
},
|
},
|
||||||
{"invalid", []string{"keys", "--not-a-flag=git"}, true, "Incorrect Usage: flag provided but not defined: -not-a-flag\n\n"},
|
{"invalid", []string{"keys", "--not-a-flag=git"}, true, "Incorrect Usage: flag provided but not defined: -not-a-flag\n\n"},
|
||||||
}
|
}
|
||||||
|
@ -59,4 +59,5 @@ func Test_CmdKeys(t *testing.T) {
|
||||||
os.Stdout = realStdout
|
os.Stdout = realStdout
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@ package private
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
)
|
)
|
||||||
|
@ -27,3 +29,26 @@ func UpdatePublicKeyInRepo(keyID, repoID int64) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AuthorizedPublicKeyByContent searches content as prefix (leak e-mail part)
|
||||||
|
// and returns public key found.
|
||||||
|
func AuthorizedPublicKeyByContent(content string) (string, error) {
|
||||||
|
// Ask for running deliver hook and test pull request tasks.
|
||||||
|
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/ssh/authorized_keys")
|
||||||
|
req := newInternalRequest(reqURL, "POST")
|
||||||
|
req.Param("content", content)
|
||||||
|
resp, err := req.Response()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// All 2XX status codes are accepted and others will return an error
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return "", fmt.Errorf("Failed to update public key: %s", decodeJSONError(resp).Err)
|
||||||
|
}
|
||||||
|
bs, err := ioutil.ReadAll(resp.Body)
|
||||||
|
|
||||||
|
return string(bs), err
|
||||||
|
}
|
||||||
|
|
|
@ -76,6 +76,7 @@ func CheckUnitUser(ctx *macaron.Context) {
|
||||||
// These APIs will be invoked by internal commands for example `gitea serv` and etc.
|
// These APIs will be invoked by internal commands for example `gitea serv` and etc.
|
||||||
func RegisterRoutes(m *macaron.Macaron) {
|
func RegisterRoutes(m *macaron.Macaron) {
|
||||||
m.Group("/", func() {
|
m.Group("/", func() {
|
||||||
|
m.Post("/ssh/authorized_keys", AuthorizedPublicKeyByContent)
|
||||||
m.Post("/ssh/:id/update/:repoid", UpdatePublicKeyInRepo)
|
m.Post("/ssh/:id/update/:repoid", UpdatePublicKeyInRepo)
|
||||||
m.Get("/hook/pre-receive/:owner/:repo", HookPreReceive)
|
m.Get("/hook/pre-receive/:owner/:repo", HookPreReceive)
|
||||||
m.Get("/hook/post-receive/:owner/:repo", HookPostReceive)
|
m.Get("/hook/post-receive/:owner/:repo", HookPostReceive)
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
package private
|
package private
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
|
||||||
|
@ -17,7 +19,7 @@ func UpdatePublicKeyInRepo(ctx *macaron.Context) {
|
||||||
keyID := ctx.ParamsInt64(":id")
|
keyID := ctx.ParamsInt64(":id")
|
||||||
repoID := ctx.ParamsInt64(":repoid")
|
repoID := ctx.ParamsInt64(":repoid")
|
||||||
if err := models.UpdatePublicKeyUpdated(keyID); err != nil {
|
if err := models.UpdatePublicKeyUpdated(keyID); err != nil {
|
||||||
ctx.JSON(500, map[string]interface{}{
|
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
|
||||||
"err": err.Error(),
|
"err": err.Error(),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
|
@ -29,18 +31,33 @@ func UpdatePublicKeyInRepo(ctx *macaron.Context) {
|
||||||
ctx.PlainText(200, []byte("success"))
|
ctx.PlainText(200, []byte("success"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.JSON(500, map[string]interface{}{
|
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
|
||||||
"err": err.Error(),
|
"err": err.Error(),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
deployKey.UpdatedUnix = timeutil.TimeStampNow()
|
deployKey.UpdatedUnix = timeutil.TimeStampNow()
|
||||||
if err = models.UpdateDeployKeyCols(deployKey, "updated_unix"); err != nil {
|
if err = models.UpdateDeployKeyCols(deployKey, "updated_unix"); err != nil {
|
||||||
ctx.JSON(500, map[string]interface{}{
|
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
|
||||||
"err": err.Error(),
|
"err": err.Error(),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.PlainText(200, []byte("success"))
|
ctx.PlainText(http.StatusOK, []byte("success"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuthorizedPublicKeyByContent searches content as prefix (leak e-mail part)
|
||||||
|
// and returns public key found.
|
||||||
|
func AuthorizedPublicKeyByContent(ctx *macaron.Context) {
|
||||||
|
content := ctx.Query("content")
|
||||||
|
|
||||||
|
publicKey, err := models.SearchPublicKeyByContent(content)
|
||||||
|
if err != nil {
|
||||||
|
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
|
||||||
|
"err": err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.PlainText(http.StatusOK, []byte(publicKey.AuthorizedString()))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue