Skip to content

Commit

Permalink
Support package signatures (#760)
Browse files Browse the repository at this point in the history
* Support package signatures

* Adjust tests

* Update CHANGELOG

* WIP

* WIP

* Use signature_path

* Fixes
  • Loading branch information
mtojek authored Oct 25, 2021
1 parent a201f80 commit 99a68bc
Show file tree
Hide file tree
Showing 10 changed files with 113 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

* Update APM Go Agent to 1.14.0. [#759](https://github.com/elastic/package-registry/pull/759)
* Update Gorilla to 1.8.0 [#759](https://github.com/elastic/package-registry/pull/759)
* Support package signatures [#760](https://github.com/elastic/package-registry/pull/760)

### Deprecated

Expand Down
2 changes: 2 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ func mustLoadRouter(config *Config, indexer Indexer) *mux.Router {

func getRouter(config *Config, indexer Indexer) (*mux.Router, error) {
artifactsHandler := artifactsHandler(indexer, config.CacheTimeCatchAll)
signaturesHandler := signaturesHandler(indexer, config.CacheTimeCatchAll)
faviconHandleFunc, err := faviconHandler(config.CacheTimeCatchAll)
if err != nil {
return nil, err
Expand All @@ -248,6 +249,7 @@ func getRouter(config *Config, indexer Indexer) (*mux.Router, error) {
router.HandleFunc("/health", healthHandler)
router.HandleFunc("/favicon.ico", faviconHandleFunc)
router.HandleFunc(artifactsRouterPath, artifactsHandler)
router.HandleFunc(signaturesRouterPath, signaturesHandler)
router.HandleFunc(packageIndexRouterPath, packageIndexHandler)
router.HandleFunc(staticRouterPath, staticHandler)
router.Use(loggingMiddleware)
Expand Down
25 changes: 25 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,31 @@ func TestArtifacts(t *testing.T) {
}
}

func TestSignatures(t *testing.T) {
indexer := packages.NewZipFileSystemIndexer("./testdata/local-storage")

err := indexer.Init(context.Background())
require.NoError(t, err)

signaturesHandler := signaturesHandler(indexer, testCacheTime)

tests := []struct {
endpoint string
path string
file string
handler func(w http.ResponseWriter, r *http.Request)
}{
{"/epr/example/example-1.0.1.zip.sig", signaturesRouterPath, "example-1.0.1.zip.sig", signaturesHandler},
{"/epr/example/example-0.0.1.zip.sig", signaturesRouterPath, "missing-signature.txt", signaturesHandler},
}

for _, test := range tests {
t.Run(test.endpoint, func(t *testing.T) {
runEndpoint(t, test.endpoint, test.path, test.file, test.handler)
})
}
}

func TestStatics(t *testing.T) {
packagesBasePaths := []string{"./testdata/package"}
indexer := packages.NewFileSystemIndexer(packagesBasePaths...)
Expand Down
4 changes: 4 additions & 0 deletions packages/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,7 @@ func ServeFile(w http.ResponseWriter, r *http.Request, p *Package, name string)

http.ServeContent(w, r, name, stat.ModTime(), f)
}

func ServeSignature(w http.ResponseWriter, r *http.Request, p *Package) {
http.ServeFile(w, r, p.BasePath+".sig")
}
18 changes: 18 additions & 0 deletions packages/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ type BasePackage struct {
Conditions *Conditions `config:"conditions,omitempty" json:"conditions,omitempty" yaml:"conditions,omitempty"`
Owner *Owner `config:"owner,omitempty" json:"owner,omitempty" yaml:"owner,omitempty"`
Categories []string `config:"categories,omitempty" json:"categories,omitempty" yaml:"categories,omitempty"`
SignaturePath string `config:"signature_path,omitempty" json:"signature_path,omitempty" yaml:"signature_path,omitempty"`
}

// BasePolicyTemplate is used for the package policy templates in the /search endpoint
Expand Down Expand Up @@ -313,6 +314,12 @@ func NewPackage(basePath string, fsBuilder FileSystemBuilder) (*Package, error)
if err != nil {
return nil, errors.Wrapf(err, "loading package data streams failed (path '%s')", p.BasePath)
}

// Read path for package signature
p.SignaturePath, err = p.GetSignaturePath()
if err != nil {
return nil, errors.Wrapf(err, "can't process the package signature")
}
return p, nil
}

Expand Down Expand Up @@ -584,3 +591,14 @@ func (p *Package) GetDownloadPath() string {
func (p *Package) GetUrlPath() string {
return path.Join(packagePathPrefix, p.Name, p.Version)
}

func (p *Package) GetSignaturePath() (string, error) {
_, err := os.Stat(p.BasePath + ".sig")
if err != nil && errors.Is(err, os.ErrNotExist) {
return "", nil
}
if err != nil {
return "", errors.Wrap(err, "can't stat signature file")
}
return p.GetDownloadPath() + ".sig", nil
}
59 changes: 59 additions & 0 deletions signatures.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

package main

import (
"log"
"net/http"
"time"

"github.com/Masterminds/semver/v3"
"github.com/gorilla/mux"
"github.com/pkg/errors"

"github.com/elastic/package-registry/packages"
)

const signaturesRouterPath = "/epr/{packageName}/{packageName:[a-z0-9_]+}-{packageVersion}.zip.sig"

var errSignatureFileNotFound = errors.New("signature file not found")

func signaturesHandler(indexer Indexer, cacheTime time.Duration) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
packageName, ok := vars["packageName"]
if !ok {
badRequest(w, "missing package name")
return
}

packageVersion, ok := vars["packageVersion"]
if !ok {
badRequest(w, "missing package version")
return
}

_, err := semver.StrictNewVersion(packageVersion)
if err != nil {
badRequest(w, "invalid package version")
return
}

opts := packages.NameVersionFilter(packageName, packageVersion)
packageList, err := indexer.Get(r.Context(), &opts)
if err != nil {
log.Printf("getting package path failed: %v", err)
http.Error(w, "internal server error", http.StatusInternalServerError)
return
}
if len(packageList) == 0 {
notFoundError(w, errSignatureFileNotFound)
return
}

cacheHeaders(w, cacheTime)
packages.ServeSignature(w, r, packageList[0])
}
}
1 change: 1 addition & 0 deletions testdata/generated/example-1.0.1.zip.sig
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
e16ddaf4f91df524b27bf4f2e4b1ac09
1 change: 1 addition & 0 deletions testdata/generated/missing-signature.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
signature file not found
1 change: 1 addition & 0 deletions testdata/generated/package-zip.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"crm",
"azure"
],
"signature_path": "/epr/example/example-1.0.1.zip.sig",
"format_version": "1.0.0",
"readme": "/package/example/1.0.1/docs/README.md",
"license": "basic",
Expand Down
1 change: 1 addition & 0 deletions testdata/local-storage/example-1.0.1.zip.sig
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
e16ddaf4f91df524b27bf4f2e4b1ac09

0 comments on commit 99a68bc

Please sign in to comment.