From 58ae3d76e63a24b66fb2ebd52e813e09bde26869 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 30 Nov 2019 10:03:24 -0500 Subject: [PATCH] Updates per single-sign-on changes --- gitsrht-update-hook/go.mod | 1 + gitsrht-update-hook/go.sum | 2 + gitsrht-update-hook/post-update.go | 4 +- gitsrht-update-hook/submitter.go | 60 +++++++++++++++++++++++++++--- gitsrht/blueprints/email.py | 2 +- 5 files changed, 62 insertions(+), 7 deletions(-) diff --git a/gitsrht-update-hook/go.mod b/gitsrht-update-hook/go.mod index 5408742..d69f424 100644 --- a/gitsrht-update-hook/go.mod +++ b/gitsrht-update-hook/go.mod @@ -3,6 +3,7 @@ module git.sr.ht/~sircmpwn/git.sr.ht/gitsrht-update-hook go 1.13 require ( + github.com/fernet/fernet-go v0.0.0-20191111064656-eff2850e6001 github.com/go-redis/redis v6.15.6+incompatible github.com/google/uuid v1.1.1 github.com/lib/pq v1.2.0 diff --git a/gitsrht-update-hook/go.sum b/gitsrht-update-hook/go.sum index d5bc92c..ea71423 100644 --- a/gitsrht-update-hook/go.sum +++ b/gitsrht-update-hook/go.sum @@ -6,6 +6,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/fernet/fernet-go v0.0.0-20191111064656-eff2850e6001 h1:/UMxx5lGDg30aioUL9e7xJnbJfJeX7vhcm57fa5udaI= +github.com/fernet/fernet-go v0.0.0-20191111064656-eff2850e6001/go.mod h1:2H9hjfbpSMHwY503FclkV/lZTBh2YlOmLLSda12uL8c= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-redis/redis v6.15.6+incompatible h1:H9evprGPLI8+ci7fxQx6WNZHJSb7be8FqJQRhdQZ5Sg= diff --git a/gitsrht-update-hook/post-update.go b/gitsrht-update-hook/post-update.go index f0cb2ff..2265762 100644 --- a/gitsrht-update-hook/post-update.go +++ b/gitsrht-update-hook/post-update.go @@ -32,7 +32,7 @@ type DbInfo struct { RepoName string Visibility string OwnerUsername string - OwnerToken string + OwnerToken *string AsyncWebhooks []WebhookSubscription SyncWebhooks []WebhookSubscription } @@ -136,6 +136,8 @@ func postUpdate() { printAutocreateInfo(context) } + initSubmitter() + payload := WebhookPayload{ Push: pushUuid, Pusher: context.User, diff --git a/gitsrht-update-hook/submitter.go b/gitsrht-update-hook/submitter.go index ea4e3aa..d98d3b6 100644 --- a/gitsrht-update-hook/submitter.go +++ b/gitsrht-update-hook/submitter.go @@ -12,19 +12,47 @@ import ( "strings" "unicode/utf8" + "github.com/fernet/fernet-go" "github.com/microcosm-cc/bluemonday" "github.com/pkg/errors" "gopkg.in/src-d/go-git.v4" "gopkg.in/src-d/go-git.v4/plumbing/object" ) +var ( + fernetKey *fernet.Key + clientId string +) + +// TODO: Consider moving Fernet code to a shared SourceHut Go module +func initSubmitter() { + netkey, ok := config.Get("sr.ht", "network-key") + if !ok { + logger.Fatal("Configuration error: [sr.ht].network-key missing") + } + var err error + fernetKey, err = fernet.DecodeKey(netkey) + if err != nil { + logger.Fatalf("Error decoding [sr.ht].network-key: %v", err) + } + clientId, ok = config.Get("git.sr.ht", "oauth-client-id") + if !ok { + logger.Fatal("Configuration error: [git.sr.ht].oauth-client-id missing") + } +} + +type InternalRequestAuthorization struct { + ClientId string `json:"client_id"` + Username string `json:"username"` +} + type BuildSubmitter interface { // Return a list of build manifests and their names FindManifests() (map[string]string, error) // Get builds.sr.ht origin GetBuildsOrigin() string // Get builds.sr.ht OAuth token - GetOauthToken() string + GetOauthToken() *string // Get a checkout-able string to append to matching source URLs GetCommitId() string // Get the build note which corresponds to this commit @@ -50,7 +78,7 @@ type GitBuildSubmitter struct { Commit *object.Commit GitOrigin string OwnerName string - OwnerToken string + OwnerToken *string RepoName string Repository *git.Repository Visibility string @@ -110,7 +138,7 @@ func (submitter GitBuildSubmitter) GetBuildsOrigin() string { return submitter.BuildOrigin } -func (submitter GitBuildSubmitter) GetOauthToken() string { +func (submitter GitBuildSubmitter) GetOauthToken() *string { return submitter.OwnerToken } @@ -167,6 +195,29 @@ type BuildSubmission struct { Url string } +func configureRequestAuthorization(submitter BuildSubmitter, + req *http.Request) { + + if submitter.GetOauthToken() != nil { + req.Header.Add("Authorization", fmt.Sprintf("token %s", + *submitter.GetOauthToken())) + } else { + auth := InternalRequestAuthorization{ + ClientId: clientId, + Username: submitter.GetOwnerName(), + } + authPayload, err := json.Marshal(&auth) + if err != nil { + logger.Fatalf("Failed to marshal internal authorization: %v", err) + } + enc, err := fernet.EncryptAndSign(authPayload, fernetKey) + if err != nil { + logger.Fatalf("Failed to encrypt internal authorization: %v", err) + } + req.Header.Add("X-Srht-Authorization", string(enc)) + } +} + // TODO: Move this to scm.sr.ht func SubmitBuild(submitter BuildSubmitter) ([]BuildSubmission, error) { manifests, err := submitter.FindManifests() @@ -204,8 +255,7 @@ func SubmitBuild(submitter BuildSubmitter) ([]BuildSubmission, error) { req, err := http.NewRequest("POST", fmt.Sprintf("%s/api/jobs", submitter.GetBuildsOrigin()), body) - req.Header.Add("Authorization", fmt.Sprintf("token %s", - submitter.GetOauthToken())) + configureRequestAuthorization(submitter, req) req.Header.Add("Content-Type", "application/json") resp, err := client.Do(req) if err != nil { diff --git a/gitsrht/blueprints/email.py b/gitsrht/blueprints/email.py index 1959869..86cdfc6 100644 --- a/gitsrht/blueprints/email.py +++ b/gitsrht/blueprints/email.py @@ -13,7 +13,7 @@ from gitsrht.git import Repository as GitRepository, commit_time, diffstat from gitsrht.git import get_log from scmsrht.access import get_repo_or_redir from srht.config import cfg, cfgi, cfgb -from srht.flask import loginrequired, current_user +from srht.oauth import loginrequired, current_user from srht.validation import Validation from tempfile import NamedTemporaryFile from textwrap import TextWrapper -- 2.38.4