From b9f663c4d8a2ed9ef4025357bb0495b61f88aeb4 Mon Sep 17 00:00:00 2001 From: guacamole Date: Sun, 27 Jun 2021 19:02:42 +0530 Subject: [PATCH] added registration,authentication and authorization Signed-off-by: guacamole --- auth/auth.go | 3 +- auth/bcrypt.go | 1 - auth/jwt.go | 72 +++++++++++++++++++--- auth/signin.go | 45 +++++++------- auth/signup.go | 7 ++- auth/validate_user.go | 41 +++++++++++++ docker/docker.go | 9 ++- main.go | 108 +++++++++++++++++++++------------ registry/registry.go | 22 +++---- server/registry/registry.go | 6 +- server/registry/resolv.go | 14 ++--- server/registry/skynetlinks.go | 2 +- server/registry/v2/blobs.go | 3 +- server/registry/v2/helpers.go | 1 - server/registry/v2/registry.go | 2 - server/registry/v2/types.go | 7 +-- server/server.go | 5 +- skynet/skynet.go | 2 +- skynet/types.go | 2 +- types/types.go | 8 +-- 20 files changed, 241 insertions(+), 119 deletions(-) create mode 100644 auth/validate_user.go diff --git a/auth/auth.go b/auth/auth.go index 842cab09..f59bd2f9 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -9,6 +9,7 @@ import ( type Authentication interface { SignUp(ctx echo.Context) error SignIn(ctx echo.Context) error + BasicAuth(username, password string) (map[string]interface{}, error) } type auth struct { @@ -19,7 +20,7 @@ type auth struct { func New(s cache.Store, c *config.RegistryConfig) Authentication { a := &auth{ store: s, - c: c, + c: c, } return a diff --git a/auth/bcrypt.go b/auth/bcrypt.go index 9418fb42..ade7919e 100644 --- a/auth/bcrypt.go +++ b/auth/bcrypt.go @@ -19,4 +19,3 @@ func (a *auth) verifyPassword(hashedPassword, currPassword string) bool { return err == nil } - diff --git a/auth/jwt.go b/auth/jwt.go index f4f59580..68263baa 100644 --- a/auth/jwt.go +++ b/auth/jwt.go @@ -6,21 +6,75 @@ import ( "time" ) -func (a *auth) newToken(u User) (string,error) { - token := jwt.New(jwt.SigningMethodHS256) +type Claims struct { + jwt.StandardClaims + Access AccessList +} - // Set claims - claims := token.Claims.(jwt.MapClaims) - claims["username"] = u.Username - claims["push"] = true - claims["exp"] = time.Now().Add(time.Hour * 24*14).Unix() +func (a *auth) newToken(u User, tokenLife int64) (string, error) { + //for now we're sending same name for sub and name. + //TODO when repositories need collaborators + claims := a.createClaims(u.Username, u.Username, tokenLife) + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) // Generate encoded token and send it as response. - fmt.Printf("secret %s:",a.c.SigningSecret) t, err := token.SignedString([]byte(a.c.SigningSecret)) if err != nil { - return "",err + return "", err } + return t, nil } + +func (a *auth) createClaims(sub, name string, tokenLife int64) Claims { + claims := Claims{ + StandardClaims: jwt.StandardClaims{ + Audience: "openregistry.dev", + ExpiresAt: tokenLife, + Id: "", + IssuedAt: time.Now().Unix(), + Issuer: "openregistry.dev", + NotBefore: time.Now().Unix(), + Subject: sub, + }, + Access: AccessList{ + { + Type: "repository", + Name: fmt.Sprintf("%s/*", name), + Actions: []string{"push", "pull"}, + }, + }, + } + + return claims +} + +type AccessList []struct { + Type string `json:"type"` + Name string `json:"name"` + Actions []string `json:"actions"` +} + +/* +claims format +{ + "iss": "auth.docker.com", + "sub": "jlhawn", + "aud": "registry.docker.com", + "exp": 1415387315, + "nbf": 1415387015, + "iat": 1415387015, + "jti": "tYJCO1c6cnyy7kAn0c7rKPgbV1H1bFws", + "access": [ + { + "type": "repository", + "name": "samalba/my-app", + "actions": [ + "pull", + "push" + ] + } + ] +} +*/ diff --git a/auth/signin.go b/auth/signin.go index fadff8a5..da13eff4 100644 --- a/auth/signin.go +++ b/auth/signin.go @@ -5,59 +5,62 @@ import ( "fmt" "github.com/labstack/echo/v4" "net/http" + "time" ) func (a *auth) SignIn(ctx echo.Context) error { var user User - if err := json.NewDecoder(ctx.Request().Body).Decode(&user); err!= nil { - return ctx.JSON(http.StatusBadRequest,echo.Map{ + if err := json.NewDecoder(ctx.Request().Body).Decode(&user); err != nil { + return ctx.JSON(http.StatusBadRequest, echo.Map{ "error": err.Error(), }) } - if user.Email == "" || user.Password == ""{ - return ctx.JSON(http.StatusBadRequest,echo.Map{ + if user.Email == "" || user.Password == "" { + return ctx.JSON(http.StatusBadRequest, echo.Map{ "error": "Email/Password cannot be empty", }) } - if err:= verifyEmail(user.Email); err!= nil { - return ctx.JSON(http.StatusBadRequest,echo.Map{ + if err := verifyEmail(user.Email); err != nil { + return ctx.JSON(http.StatusBadRequest, echo.Map{ "error": err.Error(), }) } - key := fmt.Sprintf("%s/%s",UserNameSpace,user.Email) - bz,err := a.store.Get([]byte(key)) - if err!= nil{ - return ctx.JSON(http.StatusBadRequest,echo.Map{ + key := fmt.Sprintf("%s/%s", UserNameSpace, user.Username) + bz, err := a.store.Get([]byte(key)) + if err != nil { + return ctx.JSON(http.StatusBadRequest, echo.Map{ "error": err.Error(), }) } var userFromDb User - if err := json.Unmarshal(bz,&userFromDb); err!= nil { - return ctx.JSON(http.StatusInternalServerError,echo.Map{ + if err := json.Unmarshal(bz, &userFromDb); err != nil { + return ctx.JSON(http.StatusInternalServerError, echo.Map{ "error": err.Error(), }) } - if !a.verifyPassword(userFromDb.Password,user.Password) { - return ctx.JSON(http.StatusUnauthorized,echo.Map{ + if !a.verifyPassword(userFromDb.Password, user.Password) { + return ctx.JSON(http.StatusUnauthorized, echo.Map{ "error": "invalid password", }) } - token,err := a.newToken(user) - if err!= nil{ - return ctx.JSON(http.StatusInternalServerError,echo.Map{ - "error": err.Error(), + tokenLife := time.Now().Add(time.Hour * 24 * 14).Unix() + token, err := a.newToken(user, tokenLife) + if err != nil { + return ctx.JSON(http.StatusInternalServerError, echo.Map{ + "error": err.Error(), }) } - return ctx.JSON(http.StatusOK,echo.Map{ - "message": "user authenticated", - "token": token, + return ctx.JSON(http.StatusOK, echo.Map{ + "token": token, + "expires_in": tokenLife, + "issued_at": time.Now().Unix(), }) } diff --git a/auth/signup.go b/auth/signup.go index de71a53f..118711db 100644 --- a/auth/signup.go +++ b/auth/signup.go @@ -22,7 +22,9 @@ const UserNameSpace = "users" func (a *auth) ValidateUser(u User) error { - if err := verifyEmail(u.Email); err!= nil {return err} + if err := verifyEmail(u.Email); err != nil { + return err + } key := fmt.Sprintf("%s/%s", UserNameSpace, u.Email) _, err := a.store.Get([]byte(key)) if err == nil { @@ -39,7 +41,6 @@ func (a *auth) ValidateUser(u User) error { } if bz != nil { - var userList []User fmt.Printf("%s\n", bz) if err := json.Unmarshal(bz, &userList); err != nil { @@ -169,7 +170,7 @@ func (a *auth) SignUp(ctx echo.Context) error { u.Password = hpwd bz, _ = json.Marshal(u) - key := fmt.Sprintf("%s/%s", UserNameSpace, u.Email) + key := fmt.Sprintf("%s/%s", UserNameSpace, u.Username) if err := a.store.Set([]byte(key), bz); err != nil { return ctx.JSON(http.StatusInternalServerError, echo.Map{ "error": err.Error(), diff --git a/auth/validate_user.go b/auth/validate_user.go new file mode 100644 index 00000000..66a913f1 --- /dev/null +++ b/auth/validate_user.go @@ -0,0 +1,41 @@ +package auth + +import ( + "encoding/json" + "fmt" + "github.com/labstack/echo/v4" + "time" +) + +func (a *auth) BasicAuth(username, password string) (map[string]interface{}, error) { + if username == "" || password == "" { + return nil, fmt.Errorf("Email/Password cannot be empty") + } + + key := fmt.Sprintf("%s/%s", UserNameSpace, username) + bz, err := a.store.Get([]byte(key)) + if err != nil { + return nil, err + } + + var userFromDb User + if err := json.Unmarshal(bz, &userFromDb); err != nil { + return nil, err + } + + if !a.verifyPassword(userFromDb.Password, password) { + return nil, fmt.Errorf("invalid password") + } + + tokenLife := time.Now().Add(time.Hour * 24 * 14).Unix() + token, err := a.newToken(User{Username: username}, tokenLife) + if err != nil { + return nil, err + } + + return echo.Map{ + "token": token, + "expires_in": tokenLife, + "issued_at": time.Now().Unix(), + }, nil +} diff --git a/docker/docker.go b/docker/docker.go index 81ee1a5f..0e180d27 100644 --- a/docker/docker.go +++ b/docker/docker.go @@ -38,7 +38,6 @@ func newConfigFromEnv(c *config.RegistryConfig) *Client { } } - func (c *Client) HasImage(imageID string) (bool, error) { args := filters.NewArgs() args.Add("references", StripImageTagHost(imageID)) @@ -94,10 +93,10 @@ func (c *Client) PullImage(imageID string) error { func (c *Client) PushImage(imageID string) error { r, err := c.docker.ImagePush(context.Background(), imageID, types.ImagePushOptions{ - All: false, - RegistryAuth: "anything-will-work", - PrivilegeFunc: func() (string, error) {return "", nil}, - Platform: "", + All: false, + RegistryAuth: "anything-will-work", + PrivilegeFunc: func() (string, error) { return "", nil }, + Platform: "", }) if err != nil { return err diff --git a/main.go b/main.go index 63a1b9f2..73e18bdd 100644 --- a/main.go +++ b/main.go @@ -1,11 +1,8 @@ package main import ( - "github.com/jay-dee7/parachute/auth" - "net/http" - "os" - "github.com/fatih/color" + "github.com/jay-dee7/parachute/auth" "github.com/jay-dee7/parachute/cache" "github.com/jay-dee7/parachute/config" "github.com/jay-dee7/parachute/server/registry/v2" @@ -14,6 +11,9 @@ import ( "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" "github.com/rs/zerolog" + "log" + "net/http" + "os" ) func main() { @@ -22,13 +22,12 @@ func main() { configPath = "./" } - config, err := config.Load(configPath) + cfg, err := config.Load(configPath) if err != nil { - color.Red("error reading config file: %s", err.Error()) + color.Red("error reading cfg file: %s", err.Error()) os.Exit(1) } - var errSig chan error e := echo.New() p := prometheus.NewPrometheus("echo", nil) p.Use(e) @@ -42,9 +41,9 @@ func main() { } defer localCache.Close() - authSvc := auth.New(localCache,config) + authSvc := auth.New(localCache, cfg) - skynetClient := skynet.NewClient(config) + skynetClient := skynet.NewClient(cfg) reg, err := registry.NewRegistry(skynetClient, l, localCache, e.Logger) if err != nil { @@ -56,21 +55,22 @@ func main() { Skipper: func(echo.Context) bool { return false }, - Format: "method=${method}, uri=${uri}, status=${status} latency=${latency}\n", - Output: os.Stdout, + Format: "method=${method}, uri=${uri}, status=${status} latency=${latency}\n", + Output: os.Stdout, })) e.Use(middleware.Recover()) internal := e.Group("/internal") authRouter := e.Group("/auth") - authRouter.Add(http.MethodPost,"/signup", authSvc.SignUp) - authRouter.Add(http.MethodPost,"/signin", authSvc.SignIn) - + authRouter.Add(http.MethodPost, "/signup", authSvc.SignUp) + authRouter.Add(http.MethodPost, "/signin", authSvc.SignIn) + authRouter.Add(http.MethodPost, "/token", authSvc.SignIn) internal.Add(http.MethodGet, "/metadata", localCache.Metadata) router := e.Group("/v2/:username/:imagename") + router.Use(BasicAuth(authSvc.BasicAuth)) // ALL THE HEAD METHODS // // HEAD /v2//blobs/ @@ -83,7 +83,6 @@ func main() { // PUT /v2//blobs/uploads/?digest= // router.Add(http.MethodPut, "/blobs/uploads/:uuid", reg.MonolithicUpload) - router.Add(http.MethodPut, "/blobs/uploads/", reg.CompleteUpload) // PUT /v2//blobs/uploads/?digest= @@ -117,30 +116,9 @@ func main() { // router.Add(http.MethodGet, "/blobs/:digest", reg.DownloadBlob) - e.Add(http.MethodGet, "/v2/", reg.ApiVersion) - - e.Start(config.Address()) - // e.StartTLS(config.Address(), config.TLSCertPath, config.TLSKeyPath) - -// go func() { -// if err := e.Start(config.Address()); err != nil && err != http.ErrServerClosed { -// e.Logger.Fatal("shutting down the server") -// } -// }() - -// // Wait for interrupt signal to gracefully shutdown the server with a timeout of 10 seconds. -// // Use a buffered channel to avoid missing signals as recommended for signal.Notify -// quit := make(chan os.Signal, 1) -// signal.Notify(quit, os.Interrupt) -// <-quit -// ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) -// defer cancel() + e.Add(http.MethodGet, "/v2/", reg.ApiVersion, BasicAuth(authSvc.BasicAuth)) -// if err := e.Shutdown(ctx); err != nil { -// e.Logger.Fatal(err) -// } - - color.Yellow("docker registry server stopped: %s", <-errSig) + log.Fatalln(e.Start(cfg.Address())) } func setupLogger() zerolog.Logger { @@ -151,3 +129,57 @@ func setupLogger() zerolog.Logger { return l } + +//when we use JWT +/*AuthMiddleware +HTTP/1.1 401 Unauthorized +Content-Type: application/json; charset=utf-8 +Docker-Distribution-Api-Version: registry/2.0 +Www-Authenticate: Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:samalba/my-app:pull,push" +Date: Thu, 10 Sep 2015 19:32:31 GMT +Content-Length: 235 +Strict-Transport-Security: max-age=31536000 + +{"errors":[{"code":"UNAUTHORIZED","message":"","detail":}]} +*/ +//var wwwAuthenticate = `Bearer realm="http://0.0.0.0:5000/auth/token",service="http://0.0.0.0:5000",scope="repository:%s` + +func BasicAuth(authfn func(string, string) (map[string]interface{}, error)) echo.MiddlewareFunc { + return middleware.BasicAuth(func(username string, password string, ctx echo.Context) (bool, error) { + + if ctx.Request().RequestURI != "/v2/" { + if ctx.Request().Method == http.MethodHead || ctx.Request().Method == http.MethodGet { + return true, nil + } + } + + color.Red("request uri %s", ctx.Request().RequestURI) + + if ctx.Request().RequestURI == "/v2/" { + color.Blue("username %s password %s\n", username, password) + _, err := authfn(username, password) + if err != nil { + return false, ctx.NoContent(http.StatusUnauthorized) + } + return true, nil + } + + usernameFromNameSpace := ctx.Param("username") + if usernameFromNameSpace != username { + var errMsg registry.RegistryErrors + errMsg.Errors = append(errMsg.Errors, registry.RegistryError{ + Code: registry.RegistryErrorCodeDenied, + Message: "not authorised", + Detail: nil, + }) + return false, ctx.JSON(http.StatusForbidden, errMsg) + } + resp, err := authfn(username, password) + if err != nil { + return false, err + } + + ctx.Set("basic_auth", resp) + return true, nil + }) +} diff --git a/registry/registry.go b/registry/registry.go index 2524c973..8121a7bf 100644 --- a/registry/registry.go +++ b/registry/registry.go @@ -113,7 +113,7 @@ func (r *Registry) PullImage(skynetLink string) (string, error) { return imageID, nil } -func (r *Registry) retag(imageID, dockerHash string) error{ +func (r *Registry) retag(imageID, dockerHash string) error { if err := r.dockerClient.TagImage(imageID, dockerHash); err != nil { r.Debugf("registry -> error tagging image: %s", err.Error()) return err @@ -127,8 +127,8 @@ func (r *Registry) untar(reader io.Reader, dst string) error { for { h, err := tr.Next() - switch{ - case err == io.EOF : + switch { + case err == io.EOF: return nil case err != nil: return err @@ -145,7 +145,7 @@ func (r *Registry) untar(reader io.Reader, dst string) error { return err } } - case tar.TypeReg: + case tar.TypeReg: f, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, os.FileMode(h.Mode)) if err != nil { return err @@ -184,7 +184,7 @@ func (r *Registry) Debugf(s string, args ...interface{}) { } } -func (r *Registry) writeJSON(data interface{}, path string) error{ +func (r *Registry) writeJSON(data interface{}, path string) error { bz, err := json.Marshal(data) if err != nil { return err @@ -357,9 +357,9 @@ func (r *Registry) dirSetup(tmp, imageID string) (string, error) { } } - r.createDirs(workdir+name) + r.createDirs(workdir + name) - manifestJSON, err := r.readJSONArray(tmp+"/manifest.json") + manifestJSON, err := r.readJSONArray(tmp + "/manifest.json") if err != nil { return "", err } @@ -406,7 +406,7 @@ func (r *Registry) dirSetup(tmp, imageID string) (string, error) { writeManifest := func() error { tag := ref(imageID) if tag != "latest" { - if err = r.writeJSON(mf, workdir + "/manifests/latest"); err != nil { + if err = r.writeJSON(mf, workdir+"/manifests/latest"); err != nil { return err } } @@ -433,8 +433,8 @@ func (r *Registry) dirSetup(tmp, imageID string) (string, error) { func (r *Registry) createDirs(workdir string) { os.MkdirAll(workdir, os.ModePerm) - os.MkdirAll(workdir + "/manifests", os.ModePerm) - os.MkdirAll(workdir + "/blobs", os.ModePerm) + os.MkdirAll(workdir+"/manifests", os.ModePerm) + os.MkdirAll(workdir+"/blobs", os.ModePerm) } func (r *Registry) readJSON(path string) (map[string]map[string]string, error) { @@ -471,7 +471,7 @@ func (r *Registry) sanitizeImageName(imageID string) string { } func (r *Registry) runServer() { - timeout := time.Duration(5*time.Second) + timeout := time.Duration(5 * time.Second) client := &http.Client{ Timeout: timeout, diff --git a/server/registry/registry.go b/server/registry/registry.go index 5c3c7648..771051e6 100644 --- a/server/registry/registry.go +++ b/server/registry/registry.go @@ -97,9 +97,11 @@ func Logger(l zerolog.Logger) Option { func (r *registry) skynetURL(s []string) string { skynetLink := s[0] skynetLink = strings.TrimPrefix(skynetLink, "sia://") - uri := fmt.Sprintf("%s/%s", r.c.SkynetPortalURL, "/" + skynetLink) + uri := fmt.Sprintf("%s/%s", r.c.SkynetPortalURL, "/"+skynetLink) - lm := make(logMsg); lm["uri"] = uri; r.debugf(lm) + lm := make(logMsg) + lm["uri"] = uri + r.debugf(lm) return uri } diff --git a/server/registry/resolv.go b/server/registry/resolv.go index 61ad811c..02466516 100644 --- a/server/registry/resolv.go +++ b/server/registry/resolv.go @@ -12,7 +12,6 @@ import ( "github.com/jay-dee7/parachute/skynet" ) - type SkynetLinkResolver interface { Resolve(repo string, refernce string) []string } @@ -48,7 +47,7 @@ type fileResolver struct { func NewFileResolver(uri string) SkynetLinkResolver { p := filepath.Clean(strings.TrimPrefix(uri, "file:")) - return &fileResolver{ root: p } + return &fileResolver{root: p} } func (r *fileResolver) Resolve(repo, ref string) []string { @@ -78,12 +77,12 @@ func (r *fileResolver) Resolve(repo, ref string) []string { } type skynetResolver struct { - client *skynet.Client + client *skynet.Client skynetLink string } -func NewSkynetResolver(client *skynet.Client, root string) (SkynetLinkResolver,) { - return &skynetResolver{ client: client, skynetLink: root,} +func NewSkynetResolver(client *skynet.Client, root string) SkynetLinkResolver { + return &skynetResolver{client: client, skynetLink: root} } func (r *skynetResolver) Resolve(repo, ref string) []string { @@ -109,7 +108,6 @@ func (r *skynetResolver) Resolve(repo, ref string) []string { return nil } - func (r *skynetResolver) getContent(repo, ref string) ([]byte, error) { resp, err := r.client.Download(fmt.Sprintf("%s/%s/%s", r.skynetLink, repo, ref)) if err != nil { @@ -130,9 +128,9 @@ func NewResolver(client *skynet.Client, list []string) SkynetLinkResolver { for _, l := range list { switch { - case strings.HasPrefix(l , "file:"): + case strings.HasPrefix(l, "file:"): resolvers = append(resolvers, NewFileResolver(l)) - case strings.HasPrefix(l , "/skynet/"): + case strings.HasPrefix(l, "/skynet/"): resolvers = append(resolvers, NewSkynetResolver(client, l)) default: resolvers = append(resolvers, NewSkynetResolver(client, l)) diff --git a/server/registry/skynetlinks.go b/server/registry/skynetlinks.go index 5d1941b7..712533f1 100644 --- a/server/registry/skynetlinks.go +++ b/server/registry/skynetlinks.go @@ -11,7 +11,7 @@ import ( type skynetStore struct { skynetLinks map[string]string - location string + location string sync.RWMutex } diff --git a/server/registry/v2/blobs.go b/server/registry/v2/blobs.go index 7accd239..b84c1945 100644 --- a/server/registry/v2/blobs.go +++ b/server/registry/v2/blobs.go @@ -151,14 +151,13 @@ func (b *blobs) UploadBlob(ctx echo.Context) error { return ctx.JSONBlob(http.StatusRequestedRangeNotSatisfiable, errMsg) } - if start != len(b.uploads[uuid]) { errMsg := b.errorResponse(RegistryErrorCodeBlobUploadUnknown, "content range mismatch", nil) return ctx.JSONBlob(http.StatusRequestedRangeNotSatisfiable, errMsg) } buf := bytes.NewBuffer(b.uploads[uuid]) // 90 - io.Copy(buf, ctx.Request().Body) // 10 + io.Copy(buf, ctx.Request().Body) // 10 defer ctx.Request().Body.Close() b.uploads[uuid] = buf.Bytes() diff --git a/server/registry/v2/helpers.go b/server/registry/v2/helpers.go index f74226de..5e1c2d60 100644 --- a/server/registry/v2/helpers.go +++ b/server/registry/v2/helpers.go @@ -73,4 +73,3 @@ func (r *registry) getHttpUrlFromSkylink(s string) string { link := strings.TrimPrefix(s, "sia://") return fmt.Sprintf("https://skyportal.xyz/%s", link) } - diff --git a/server/registry/v2/registry.go b/server/registry/v2/registry.go index 3481087d..b8f11188 100644 --- a/server/registry/v2/registry.go +++ b/server/registry/v2/registry.go @@ -81,7 +81,6 @@ const ( RegistryErrorCodeUnsupported = "UNSUPPORTED" // operation is not supported ) - type ( registry struct { log zerolog.Logger @@ -138,7 +137,6 @@ type ( } ) - type Registry interface { UploadProgress(ctx echo.Context) error diff --git a/server/registry/v2/types.go b/server/registry/v2/types.go index 29c850f8..9c8cfce0 100644 --- a/server/registry/v2/types.go +++ b/server/registry/v2/types.go @@ -206,7 +206,7 @@ func (r *registry) ManifestExists(ctx echo.Context) error { if err != nil { details := echo.Map{ "skynet": "skynet link not found", - "error": err.Error(), + "error": err.Error(), } r.debugf(logMsg(details)) @@ -349,7 +349,6 @@ func (r *registry) PullManifest(ctx echo.Context) error { namespace := ctx.Param("username") + "/" + ctx.Param("imagename") ref := ctx.Param("reference") - bz, err := r.localCache.Get([]byte(namespace)) if err != nil { errMsg := r.errorResponse(RegistryErrorCodeManifestUnknown, err.Error(), nil) @@ -447,7 +446,6 @@ func (r *registry) PushManifest(ctx echo.Context) error { }, } - r.localCache.Update([]byte(namespace), metadata.Bytes()) ctx.Response().Header().Set("Docker-Content-Digest", digest) ctx.Response().Header().Set("X-Docker-Content-ID", skylink) @@ -524,7 +522,7 @@ func (r *registry) PullLayer(ctx echo.Context) error { dig := digest(bz) if dig != clientDigest { details := map[string]interface{}{ - "clientDigest": clientDigest, + "clientDigest": clientDigest, "computedDigest": dig, } errMsg := r.errorResponse(RegistryErrorCodeBlobUploadUnknown, "client digest is different than computed digest", details) @@ -676,4 +674,3 @@ func (r *registry) ApiVersion(ctx echo.Context) error { ctx.Response().Header().Set(HeaderDockerDistributionApiVersion, "registry/2.0") return ctx.String(http.StatusOK, "OK\n") } - diff --git a/server/server.go b/server/server.go index b04aa148..ec985ddc 100644 --- a/server/server.go +++ b/server/server.go @@ -11,9 +11,9 @@ import ( ) type Server struct { - c *config.RegistryConfig + c *config.RegistryConfig ln net.Listener - l zerolog.Logger + l zerolog.Logger } type InfoResponse struct { @@ -24,7 +24,6 @@ type InfoResponse struct { Problematic []string `json:"problematic"` } - func NewServer(logger zerolog.Logger, c *config.RegistryConfig) *Server { return &Server{c: c, ln: nil, l: logger} } diff --git a/skynet/skynet.go b/skynet/skynet.go index 73970a43..50bd0313 100644 --- a/skynet/skynet.go +++ b/skynet/skynet.go @@ -83,7 +83,7 @@ func (c *Client) AddImage(namespace string, manifests map[string][]byte, layers return link, err } -func (c *Client) Metadata(skylink string) (uint64, bool){ +func (c *Client) Metadata(skylink string) (uint64, bool) { opts := skynet.DefaultMetadataOptions info, err := c.skynet.Metadata(skylink, opts) if err != nil { diff --git a/skynet/types.go b/skynet/types.go index 37a39124..e52f946a 100644 --- a/skynet/types.go +++ b/skynet/types.go @@ -28,7 +28,7 @@ type ( } Image struct { - Layers map[string][]byte + Layers map[string][]byte Manifests map[string][]byte } ) diff --git a/types/types.go b/types/types.go index bd84eda7..ef5bad29 100644 --- a/types/types.go +++ b/types/types.go @@ -18,10 +18,10 @@ type ( } ImageManifest struct { - SchemaVersion int `json:"schemaVersion"` - MediaType string `json:"mediaType"` + SchemaVersion int `json:"schemaVersion"` + MediaType string `json:"mediaType"` Layers []*Layer `json:"layers"` - Config Config `json:"config"` + Config Config `json:"config"` } Layer struct { @@ -41,7 +41,7 @@ type ( } ) -func (md Metadata) Digests() []string{ +func (md Metadata) Digests() []string { digests := []string{md.Manifest.Config.Digest} for _, l := range md.Manifest.Layers {