Просмотр исходного кода

Merge pull request #272 from porter-dev/beta.3.github-actions-ci

token login fixes and checkout code
abelanger5 5 лет назад
Родитель
Сommit
59f09bbdb9

Разница между файлами не показана из-за своего большого размера
+ 10196 - 1
dashboard/package-lock.json


+ 14 - 5
internal/integrations/ci/actions/actions.go

@@ -75,12 +75,13 @@ func (g *GithubActions) Setup() (string, error) {
 		return "", err
 	}
 
-	return g.commitGithubFile(client, fileBytes)
+	return g.commitGithubFile(client, g.getPorterYMLFileName(), fileBytes)
 }
 
 type GithubActionYAMLStep struct {
 	Name string `yaml:"name"`
 	ID   string `yaml:"id"`
+	Uses string `yaml:"uses"`
 	Run  string `yaml:"run"`
 }
 
@@ -119,6 +120,7 @@ func (g *GithubActions) GetGithubActionYAML() ([]byte, error) {
 			"porter-deploy": GithubActionYAMLJob{
 				RunsOn: "ubuntu-latest",
 				Steps: []GithubActionYAMLStep{
+					getCheckoutCodeStep(),
 					getDownloadPorterStep(),
 					getConfigurePorterStep(g.getPorterTokenSecretName()),
 					getDockerBuildPushStep(g.DockerFilePath, g.ImageRepoURL),
@@ -199,18 +201,25 @@ func (g *GithubActions) getWebhookSecretName() string {
 	)
 }
 
+func (g *GithubActions) getPorterYMLFileName() string {
+	return fmt.Sprintf("porter_%s.yml", strings.Replace(
+		strings.ToLower(g.ReleaseName), "-", "_", -1),
+	)
+}
+
 func (g *GithubActions) getPorterTokenSecretName() string {
 	return fmt.Sprintf("PORTER_TOKEN_%d", g.ProjectID)
 }
 
 func (g *GithubActions) commitGithubFile(
 	client *github.Client,
+	filename string,
 	contents []byte,
 ) (string, error) {
-	fmt.Println("GITHUB ACTION CONTENTS ARE", string(contents))
+	filepath := ".github/workflows/" + filename
 
 	opts := &github.RepositoryContentFileOptions{
-		Message: github.String("Create porter.yml file"),
+		Message: github.String(fmt.Sprintf("Create %s file", filename)),
 		Content: contents,
 		Branch:  github.String(g.defaultBranch),
 		Committer: &github.CommitAuthor{
@@ -219,11 +228,11 @@ func (g *GithubActions) commitGithubFile(
 		},
 	}
 
-	resp, _, err := client.Repositories.CreateFile(
+	resp, _, err := client.Repositories.UpdateFile(
 		context.TODO(),
 		g.GitRepoOwner,
 		g.GitRepoName,
-		".github/workflows/porter.yml",
+		filepath,
 		opts,
 	)
 

+ 7 - 0
internal/integrations/ci/actions/steps.go

@@ -2,6 +2,13 @@ package actions
 
 import "fmt"
 
+func getCheckoutCodeStep() GithubActionYAMLStep {
+	return GithubActionYAMLStep{
+		Name: "Checkout code",
+		Uses: "actions/checkout@v2.3.4",
+	}
+}
+
 const download string = `
 name=$(curl -s https://api.github.com/repos/porter-dev/porter/releases/latest | grep "browser_download_url.*/porter_.*_Linux_x86_64\.zip" | cut -d ":" -f 2,3 | tr -d \")
 name=$(basename $name)

+ 24 - 0
server/api/api.go

@@ -2,11 +2,14 @@ package api
 
 import (
 	"fmt"
+	"net/http"
+	"strings"
 
 	"github.com/go-playground/locales/en"
 	ut "github.com/go-playground/universal-translator"
 	vr "github.com/go-playground/validator/v10"
 	"github.com/porter-dev/porter/internal/auth/sessionstore"
+	"github.com/porter-dev/porter/internal/auth/token"
 	"github.com/porter-dev/porter/internal/oauth"
 	"golang.org/x/oauth2"
 	"gorm.io/gorm"
@@ -75,6 +78,7 @@ type App struct {
 	db         *gorm.DB
 	validator  *vr.Validate
 	translator *ut.Translator
+	tokenConf  *token.TokenGeneratorConf
 }
 
 // New returns a new App instance
@@ -142,5 +146,25 @@ func New(conf *AppConfig) (*App, error) {
 		})
 	}
 
+	app.tokenConf = &token.TokenGeneratorConf{
+		TokenSecret: conf.ServerConf.TokenGeneratorSecret,
+	}
+
 	return app, nil
 }
+
+func (app *App) getTokenFromRequest(r *http.Request) *token.Token {
+	reqToken := r.Header.Get("Authorization")
+
+	splitToken := strings.Split(reqToken, "Bearer")
+
+	if len(splitToken) != 2 {
+		return nil
+	}
+
+	reqToken = strings.TrimSpace(splitToken[1])
+
+	tok, _ := token.GetTokenFromEncoded(reqToken, app.tokenConf)
+
+	return tok
+}

+ 8 - 7
server/api/helpers_test.go

@@ -59,13 +59,14 @@ func newTester(canQuery bool) *tester {
 	appConf := config.Conf{
 		Debug: true,
 		Server: config.ServerConf{
-			Port:         8080,
-			CookieName:   "porter",
-			CookieSecret: []byte("secret"),
-			TimeoutRead:  time.Second * 5,
-			TimeoutWrite: time.Second * 10,
-			TimeoutIdle:  time.Second * 15,
-			IsTesting:    true,
+			Port:                 8080,
+			CookieName:           "porter",
+			CookieSecrets:        []string{"secret"},
+			TimeoutRead:          time.Second * 5,
+			TimeoutWrite:         time.Second * 10,
+			TimeoutIdle:          time.Second * 15,
+			IsTesting:            true,
+			TokenGeneratorSecret: "secret",
 		},
 		// unimportant here
 		Db: config.DBConf{},

+ 1 - 1
server/api/oauth_github_handler.go

@@ -229,7 +229,7 @@ func (app *App) upsertUserFromToken(tok *oauth2.Token) (*models.User, error) {
 			return nil, err
 		}
 	} else if err != nil {
-		return nil, fmt.Errorf("unexpected error occurred:", err.Error())
+		return nil, fmt.Errorf("unexpected error occurred:%s", err.Error())
 	}
 
 	return user, nil

+ 20 - 0
server/api/user_handler.go

@@ -68,6 +68,26 @@ func (app *App) HandleCreateUser(w http.ResponseWriter, r *http.Request) {
 
 // HandleAuthCheck checks whether current session is authenticated and returns user ID if so.
 func (app *App) HandleAuthCheck(w http.ResponseWriter, r *http.Request) {
+	// first, check for token
+	tok := app.getTokenFromRequest(r)
+
+	if tok != nil {
+		// read the user
+		user, err := app.Repo.User.ReadUser(tok.IBy)
+
+		if err != nil {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+			return
+		}
+
+		if err := app.sendUser(w, tok.IBy, user.Email, ""); err != nil {
+			app.handleErrorFormDecoding(err, ErrUserDecode, w)
+			return
+		}
+
+		return
+	}
+
 	session, err := app.Store.Get(r, app.ServerConf.CookieName)
 
 	if err != nil {

+ 49 - 0
server/api/user_handler_test.go

@@ -2,6 +2,7 @@ package api_test
 
 import (
 	"encoding/json"
+	"fmt"
 	"net/http"
 	"net/http/httptest"
 	"reflect"
@@ -9,6 +10,7 @@ import (
 	"testing"
 
 	"github.com/go-test/deep"
+	"github.com/porter-dev/porter/internal/auth/token"
 	"github.com/porter-dev/porter/internal/models"
 )
 
@@ -106,6 +108,53 @@ func TestHandleAuthCheck(t *testing.T) {
 	testUserRequests(t, authCheckTests, true)
 }
 
+func TestHandleAuthCheckToken(t *testing.T) {
+	tester := newTester(true)
+
+	initUserDefault(tester)
+	initProject(tester)
+
+	// generate a new token
+	tokGen, _ := token.GetTokenForAPI(1, 1)
+
+	tok, _ := tokGen.EncodeToken(&token.TokenGeneratorConf{
+		TokenSecret: "secret",
+	})
+
+	req, err := http.NewRequest(
+		"GET",
+		"/api/auth/check",
+		strings.NewReader(""),
+	)
+
+	tester.req = req
+	req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", tok))
+	tester.execute()
+
+	rr := tester.rr
+
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// first, check that the status matches
+	if status := rr.Code; status != 200 {
+		t.Errorf("%s, handler returned wrong status code: got %v want %v",
+			"auth check token", status, 200)
+	}
+
+	gotBody := &models.UserExternal{}
+	expBody := &models.UserExternal{}
+
+	json.Unmarshal(tester.rr.Body.Bytes(), gotBody)
+	json.Unmarshal([]byte(`{"id":1,"email":"belanger@getporter.dev"}`), expBody)
+
+	if !reflect.DeepEqual(gotBody, expBody) {
+		t.Errorf("%s, handler returned wrong body: got %v want %v",
+			"auth check token", gotBody, expBody)
+	}
+}
+
 var createUserTests = []*userTest{
 	&userTest{
 		msg:      "Create user",

+ 19 - 8
server/router/middleware/auth.go

@@ -131,18 +131,19 @@ type bodyDOIntegrationID struct {
 // the one stored in the session
 func (auth *Auth) DoesUserIDMatch(next http.Handler, loc IDLocation) http.Handler {
 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		var err error
+		id, err := findUserIDInRequest(r, loc)
+
 		// first check for token
 		tok := auth.getTokenFromRequest(r)
 
-		if tok != nil && tok.SubKind == token.User && auth.doesSessionMatchID(r, tok.IBy) {
+		if err != nil {
+			http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
+			return
+		} else if tok != nil && tok.IBy == uint(id) {
 			next.ServeHTTP(w, r)
 			return
-		}
-
-		var err error
-		id, err := findUserIDInRequest(r, loc)
-
-		if err == nil && auth.doesSessionMatchID(r, uint(id)) {
+		} else if auth.doesSessionMatchID(r, uint(id)) {
 			next.ServeHTTP(w, r)
 		} else {
 			http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
@@ -657,6 +658,14 @@ func (auth *Auth) doesSessionMatchID(r *http.Request, id uint) bool {
 func (auth *Auth) isLoggedIn(w http.ResponseWriter, r *http.Request) bool {
 	// first check for Bearer token
 
+	tok := auth.getTokenFromRequest(r)
+
+	fmt.Println("CHECKED TOKEN FROM REQUEST", tok)
+
+	if tok != nil {
+		return true
+	}
+
 	session, err := auth.store.Get(r, auth.cookieName)
 	if err != nil {
 		session.Values["authenticated"] = false
@@ -683,7 +692,9 @@ func (auth *Auth) getTokenFromRequest(r *http.Request) *token.Token {
 
 	reqToken = strings.TrimSpace(splitToken[1])
 
-	tok, _ := token.GetTokenFromEncoded(reqToken, auth.tokenConf)
+	tok, err := token.GetTokenFromEncoded(reqToken, auth.tokenConf)
+
+	fmt.Printf("ERROR WAS %v\n", err)
 
 	return tok
 }

Некоторые файлы не были показаны из-за большого количества измененных файлов