Skip to content

Commit

Permalink
feat: Build automation store rewrite
Browse files Browse the repository at this point in the history
Signed-off-by: jay-dee7 <me@jsdp.dev>
  • Loading branch information
jay-dee7 committed Oct 15, 2023
1 parent 27aa3f3 commit a1c2832
Show file tree
Hide file tree
Showing 51 changed files with 2,324 additions and 696 deletions.
11 changes: 9 additions & 2 deletions auth/basic_auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,14 @@ func (a *auth) buildBasicAuthenticationHeader(repoNamespace string) string {
)
}

func (a *auth) checkJWT(authHeader string) bool {
func (a *auth) checkJWT(authHeader string, cookies []*http.Cookie) bool {
for _, cookie := range cookies {
if cookie.Name == AccessCookieKey {
// early return if access_token is found in cookies
return true
}
}

parts := strings.Split(authHeader, " ")
if len(parts) != 2 {
return false
Expand Down Expand Up @@ -154,7 +161,7 @@ func (a *auth) SkipBasicAuth(ctx echo.Context) bool {
authHeader := ctx.Request().Header.Get(AuthorizationHeaderKey)

// if Authorization header contains JWT, we skip basic auth and perform a JWT validation
if ok := a.checkJWT(authHeader); ok {
if ok := a.checkJWT(authHeader, ctx.Request().Cookies()); ok {
ctx.Set(JWT_AUTH_KEY, true)
return true
}
Expand Down
4 changes: 2 additions & 2 deletions auth/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,8 @@ func (a *auth) finishGitHubCallback(ctx echo.Context, user *v2_types.User, oauth
val := fmt.Sprintf("%s:%s", sessionId, user.ID)

sessionCookie := a.createCookie(ctx, "session_id", val, false, time.Now().Add(time.Hour*750))
accessCookie := a.createCookie(ctx, "access_token", accessToken, true, time.Now().Add(time.Hour*750))
refreshCookie := a.createCookie(ctx, "refresh_token", refreshToken, true, time.Now().Add(time.Hour*750))
accessCookie := a.createCookie(ctx, AccessCookieKey, accessToken, true, time.Now().Add(time.Hour*750))
refreshCookie := a.createCookie(ctx, RefreshCookKey, refreshToken, true, time.Now().Add(time.Hour*750))

ctx.SetCookie(accessCookie)
ctx.SetCookie(refreshCookie)
Expand Down
4 changes: 2 additions & 2 deletions auth/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,11 @@ type CreateClaimOptions struct {
func CreateClaims(opts *CreateClaimOptions) Claims {
tokenLife := time.Now().Add(time.Minute * 10)
switch opts.TokeType {
case "access_token":
case AccessCookieKey:
// TODO (jay-dee7)
// token can live for month now, but must be addressed when we implement PASETO
tokenLife = time.Now().Add(time.Hour * 750)
case "refresh_token":
case RefreshCookKey:
tokenLife = time.Now().Add(time.Hour * 750)
case "service":
tokenLife = time.Now().Add(time.Hour * 750)
Expand Down
2 changes: 1 addition & 1 deletion auth/jwt.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ func (a *auth) newToken(u *types.User) (string, error) {
Audience: a.c.Registry.FQDN,
Issuer: OpenRegistryIssuer,
Id: u.ID.String(),
TokeType: "access_token",
TokeType: AccessCookieKey,
Acl: acl,
}
claims := CreateClaims(opts)
Expand Down
15 changes: 13 additions & 2 deletions auth/jwt_middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import (
)

const (
AccessCookieKey = "access"
RefreshCookKey = "refresh"
AccessCookieKey = "access_token"
RefreshCookKey = "refresh_token"
QueryToken = "token"
)

Expand All @@ -28,16 +28,22 @@ func (a *auth) JWT() echo.MiddlewareFunc {
return false
}

if strings.HasPrefix(ctx.Request().RequestURI, "/v2/ext") {
return false
}

// if JWT_AUTH is not set, we don't need to perform JWT authentication
jwtAuth, ok := ctx.Get(JWT_AUTH_KEY).(bool)
if !ok {
a.logger.Debug().Str("method", "JWT").Str("type", "middleware").Bool("skip", true).Send()
return true
}

if jwtAuth {
return false
}

a.logger.Debug().Str("method", "JWT").Str("type", "middleware").Bool("skip", true).Send()
return true
},
ErrorHandler: func(ctx echo.Context, err error) error {
Expand All @@ -46,6 +52,7 @@ func (a *auth) JWT() echo.MiddlewareFunc {
"error": err.Error(),
"message": "missing authentication information",
})
a.logger.Debug().Err(err).Send()
a.logger.Log(ctx, err).Send()
return echoErr
},
Expand All @@ -59,8 +66,12 @@ func (a *auth) JWT() echo.MiddlewareFunc {
user, _ := a.pgStore.GetUserByID(ctx.Request().Context(), uuid.MustParse(claims.ID))
ctx.Set(string(types.UserClaimsContextKey), claims)
ctx.Set(string(types.UserContextKey), user)
a.logger.Debug().Str("method", "jwt_success_handler").Bool("success", true).Send()
return
}
}

a.logger.Debug().Str("method", "jwt_success_handler").Bool("success", false).Send()
},
SigningKey: a.c.Registry.Auth.JWTSigningPrivateKey,
SigningKeys: map[string]interface{}{},
Expand Down
4 changes: 2 additions & 2 deletions auth/renew.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func (a *auth) RenewAccessToken(ctx echo.Context) error {
opts := &WebLoginJWTOptions{
Id: userId,
Username: user.Username,
TokenType: "access_token",
TokenType: AccessCookieKey,
Audience: a.c.Registry.FQDN,
Privkey: a.c.Registry.Auth.JWTSigningPrivateKey,
Pubkey: a.c.Registry.Auth.JWTSigningPubKey,
Expand All @@ -95,7 +95,7 @@ func (a *auth) RenewAccessToken(ctx echo.Context) error {
return echoErr
}

accessCookie := a.createCookie(ctx, "access_token", tokenString, true, time.Now().Add(time.Hour))
accessCookie := a.createCookie(ctx, AccessCookieKey, tokenString, true, time.Now().Add(time.Hour))
ctx.SetCookie(accessCookie)
err = ctx.NoContent(http.StatusNoContent)
a.logger.Log(ctx, err).Send()
Expand Down
2 changes: 1 addition & 1 deletion auth/reset_password.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ func (a *auth) ForgotPassword(ctx echo.Context) error {
opts := &WebLoginJWTOptions{
Id: user.ID,
Username: user.Username,
TokenType: "access_token",
TokenType: AccessCookieKey,
Audience: a.c.Registry.FQDN,
Privkey: a.c.Registry.Auth.JWTSigningPrivateKey,
Pubkey: a.c.Registry.Auth.JWTSigningPubKey,
Expand Down
10 changes: 4 additions & 6 deletions auth/server/webauthn_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
webauthn_store "github.com/containerish/OpenRegistry/store/v2/webauthn"
"github.com/containerish/OpenRegistry/telemetry"
"github.com/containerish/OpenRegistry/types"
"github.com/fatih/color"
"github.com/google/uuid"
"github.com/labstack/echo/v4"
"github.com/uptrace/bun"
Expand Down Expand Up @@ -285,7 +284,6 @@ func (wa *webauthn_server) FinishRegistration(ctx echo.Context) error {
})
return echoErr
}
color.Red("User before finish txn: %#v", user)

opts := &webauthn.FinishRegistrationOpts{
RequestBody: ctx.Request().Body,
Expand Down Expand Up @@ -407,7 +405,7 @@ func (wa *webauthn_server) FinishLogin(ctx echo.Context) error {
accessTokenOpts := &auth.WebLoginJWTOptions{
Id: user.ID,
Username: username,
TokenType: "access_token",
TokenType: auth.AccessCookieKey,
Audience: wa.cfg.Registry.FQDN,
Privkey: wa.cfg.Registry.Auth.JWTSigningPrivateKey,
Pubkey: wa.cfg.Registry.Auth.JWTSigningPubKey,
Expand All @@ -416,7 +414,7 @@ func (wa *webauthn_server) FinishLogin(ctx echo.Context) error {
refreshTokenOpts := &auth.WebLoginJWTOptions{
Id: user.ID,
Username: username,
TokenType: "refresh_token",
TokenType: auth.RefreshCookKey,
Audience: wa.cfg.Registry.FQDN,
Privkey: wa.cfg.Registry.Auth.JWTSigningPrivateKey,
Pubkey: wa.cfg.Registry.Auth.JWTSigningPubKey,
Expand Down Expand Up @@ -472,7 +470,7 @@ func (wa *webauthn_server) FinishLogin(ctx echo.Context) error {

accessTokenCookie := auth.CreateCookie(&auth.CreateCookieOptions{
ExpiresAt: time.Now().Add(time.Hour * 750),
Name: "access_token",
Name: auth.AccessCookieKey,
Value: accessToken,
FQDN: domain,
Environment: wa.cfg.Environment,
Expand All @@ -481,7 +479,7 @@ func (wa *webauthn_server) FinishLogin(ctx echo.Context) error {

refreshTokenCookie := auth.CreateCookie(&auth.CreateCookieOptions{
ExpiresAt: time.Now().Add(time.Hour * 750), //one month
Name: "refresh_token",
Name: auth.RefreshCookKey,
Value: refreshToken,
FQDN: domain,
Environment: wa.cfg.Environment,
Expand Down
8 changes: 4 additions & 4 deletions auth/signin.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func (a *auth) SignIn(ctx echo.Context) error {
accessTokenOpts := &WebLoginJWTOptions{
Id: userFromDb.ID,
Username: userFromDb.Username,
TokenType: "access_token",
TokenType: AccessCookieKey,
Audience: a.c.Registry.FQDN,
Privkey: a.c.Registry.Auth.JWTSigningPrivateKey,
Pubkey: a.c.Registry.Auth.JWTSigningPubKey,
Expand All @@ -127,7 +127,7 @@ func (a *auth) SignIn(ctx echo.Context) error {
refreshTokenOpts := &WebLoginJWTOptions{
Id: userFromDb.ID,
Username: userFromDb.Username,
TokenType: "refresh_token",
TokenType: RefreshCookKey,
Audience: a.c.Registry.FQDN,
Privkey: a.c.Registry.Auth.JWTSigningPrivateKey,
Pubkey: a.c.Registry.Auth.JWTSigningPubKey,
Expand Down Expand Up @@ -163,8 +163,8 @@ func (a *auth) SignIn(ctx echo.Context) error {

sessionId := fmt.Sprintf("%s:%s", id, userFromDb.ID)
sessionCookie := a.createCookie(ctx, "session_id", sessionId, false, time.Now().Add(time.Hour*750))
accessCookie := a.createCookie(ctx, "access_token", access, true, time.Now().Add(time.Hour*750))
refreshCookie := a.createCookie(ctx, "refresh_token", refresh, true, time.Now().Add(time.Hour*750))
accessCookie := a.createCookie(ctx, AccessCookieKey, access, true, time.Now().Add(time.Hour*750))
refreshCookie := a.createCookie(ctx, RefreshCookKey, refresh, true, time.Now().Add(time.Hour*750))

ctx.SetCookie(accessCookie)
ctx.SetCookie(refreshCookie)
Expand Down
4 changes: 2 additions & 2 deletions auth/signout.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ func (a *auth) SignOut(ctx echo.Context) error {
return echoErr
}

ctx.SetCookie(a.createCookie(ctx, "access_token", "", true, time.Now().Add(-time.Hour*750)))
ctx.SetCookie(a.createCookie(ctx, "refresh_token", "", true, time.Now().Add(-time.Hour*750)))
ctx.SetCookie(a.createCookie(ctx, AccessCookieKey, "", true, time.Now().Add(-time.Hour*750)))
ctx.SetCookie(a.createCookie(ctx, RefreshCookKey, "", true, time.Now().Add(-time.Hour*750)))
ctx.SetCookie(a.createCookie(ctx, "session_id", "", true, time.Now().Add(-time.Hour*750)))
err = ctx.JSON(http.StatusAccepted, echo.Map{
"message": "session deleted successfully",
Expand Down
8 changes: 4 additions & 4 deletions auth/verify_email.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func (a *auth) VerifyEmail(ctx echo.Context) error {
accesssTokenOpts := &WebLoginJWTOptions{
Id: userId,
Username: user.Username,
TokenType: "access_token",
TokenType: AccessCookieKey,
Audience: a.c.Registry.FQDN,
Privkey: a.c.Registry.Auth.JWTSigningPrivateKey,
Pubkey: a.c.Registry.Auth.JWTSigningPubKey,
Expand All @@ -98,7 +98,7 @@ func (a *auth) VerifyEmail(ctx echo.Context) error {
refreshTokenOpts := &WebLoginJWTOptions{
Id: userId,
Username: user.Username,
TokenType: "refresh_token",
TokenType: RefreshCookKey,
Audience: a.c.Registry.FQDN,
Privkey: a.c.Registry.Auth.JWTSigningPrivateKey,
Pubkey: a.c.Registry.Auth.JWTSigningPubKey,
Expand Down Expand Up @@ -133,8 +133,8 @@ func (a *auth) VerifyEmail(ctx echo.Context) error {

sessionId := fmt.Sprintf("%s:%s", id, userId)
sessionCookie := a.createCookie(ctx, "session_id", sessionId, false, time.Now().Add(time.Hour*750))
accessCookie := a.createCookie(ctx, "access_token", access, true, time.Now().Add(time.Hour))
refreshCookie := a.createCookie(ctx, "refresh_token", refresh, true, time.Now().Add(time.Hour*750))
accessCookie := a.createCookie(ctx, AccessCookieKey, access, true, time.Now().Add(time.Hour))
refreshCookie := a.createCookie(ctx, RefreshCookKey, refresh, true, time.Now().Add(time.Hour*750))

ctx.SetCookie(accessCookie)
ctx.SetCookie(refreshCookie)
Expand Down
8 changes: 6 additions & 2 deletions auth/webauthn/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,13 @@ func (u *WebAuthnUser) WebAuthnCredentials() []webauthn.Credential {

func (u *WebAuthnUser) AddWebAuthNCredential(creds *webauthn.Credential) {
// initialised to non-nil value in case of first attempt
if u.credentials == nil || len(u.credentials) == 0 {
return
if u.credentials == nil {
if creds == nil || len(creds.ID) == 0 {
return
}
u.credentials = make([]webauthn.Credential, 0)
}

u.credentials = append(u.credentials, *creds)
}

Expand Down
8 changes: 4 additions & 4 deletions auth/webauthn/webauthn.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,17 @@ package webauthn

import (
"context"
"errors"
"fmt"
"io"
"log"
"strings"

"github.com/containerish/OpenRegistry/config"
webauthn_store "github.com/containerish/OpenRegistry/store/v2/webauthn"
"github.com/fatih/color"
"github.com/go-webauthn/webauthn/protocol"
"github.com/go-webauthn/webauthn/webauthn"
"github.com/google/uuid"
"github.com/jackc/pgx/v4"
)

type (
Expand Down Expand Up @@ -167,7 +166,7 @@ func (wa *webAuthnService) BeginRegistration(
user *WebAuthnUser,
) (*protocol.CredentialCreation, error) {
creds, err := wa.store.GetWebAuthnCredentials(ctx, user.ID)
if err != nil && errors.Unwrap(err) != pgx.ErrNoRows {
if err != nil && !strings.Contains(err.Error(), "no rows in result set") {
return nil, err
}

Expand Down Expand Up @@ -197,9 +196,10 @@ func (wa *webAuthnService) BeginRegistration(
if err != nil {
return nil, fmt.Errorf("ERR_WEB_AUTHN_BEGIN_REGISTRATION: %w", err)
}

// store session data in DB
if err = wa.store.AddWebAuthSessionData(ctx, user.ID, sessionData, "registration"); err != nil {
return nil, err
return nil, fmt.Errorf("ERR_WEB_AUTHN_ADD_SESSION: %w", err)
}

return credentialCreation, err
Expand Down
15 changes: 15 additions & 0 deletions cmd/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,21 @@ func createOpenRegistryTables(ctx *cli.Context, db *bun.DB) error {
)
}
color.Green(`Table "emails" created ✔︎`)
_, err = db.NewCreateTable().Model(&types.RepositoryBuild{}).Table().IfNotExists().Exec(ctx.Context)
if err != nil {
return errors.New(
color.RedString("Table=repository_builds Created=❌ Error=%s", err),
)
}
color.Green(`Table "repository_builds" created ✔︎`)

_, err = db.NewCreateTable().Model(&types.RepositoryBuildProject{}).Table().IfNotExists().Exec(ctx.Context)
if err != nil {
return errors.New(
color.RedString("Table=repository_build_projects Created=❌ Error=%s", err),
)
}
color.Green(`Table "repository_build_projects" created ✔︎`)

return nil
}
Expand Down
6 changes: 4 additions & 2 deletions cmd/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import (
"github.com/containerish/OpenRegistry/router"
github_actions_server "github.com/containerish/OpenRegistry/services/kon/github_actions/v1/server"
"github.com/containerish/OpenRegistry/store/postgres"
build_automation_store "github.com/containerish/OpenRegistry/store/postgres/build_automation"
store_v2 "github.com/containerish/OpenRegistry/store/v2"
"github.com/containerish/OpenRegistry/store/v2/automation"
"github.com/containerish/OpenRegistry/store/v2/emails"
registry_store "github.com/containerish/OpenRegistry/store/v2/registry"
"github.com/containerish/OpenRegistry/store/v2/sessions"
Expand Down Expand Up @@ -92,7 +92,8 @@ func RunRegistryServer(ctx *cli.Context) {
webauthnStore := webauthn.NewStore(rawDB)
emailStore := emails.NewStore(rawDB)

buildAutomationStore, err := build_automation_store.New(&cfg.StoreConfig)
// buildAutomationStore, err := build_automation_store.New(&cfg.StoreConfig)
buildAutomationStore, err := automation.New(rawDB, logger)
if err != nil {
color.Red("ERR_BUILD_AUTOMATION_PG_CONN: %s", err.Error())
return
Expand All @@ -118,6 +119,7 @@ func RunRegistryServer(ctx *cli.Context) {

router.Register(cfg, e, reg, authSvc, webauthnServer, ext, registryStore)
router.RegisterHealthCheckEndpoint(e, healthCheckHandler)

if cfg.Integrations.GetGithubConfig() != nil && cfg.Integrations.GetGithubConfig().Enabled {
ghApp, err := github.NewGithubApp(
cfg.Integrations.GetGithubConfig(),
Expand Down
Loading

0 comments on commit a1c2832

Please sign in to comment.