2018-06-25 06:38:11 +02:00
|
|
|
package http
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2022-08-12 14:44:54 +02:00
|
|
|
"crypto/tls"
|
2018-09-08 21:33:46 +02:00
|
|
|
"encoding/pem"
|
2020-09-21 19:47:51 +02:00
|
|
|
"errors"
|
2018-06-25 06:38:11 +02:00
|
|
|
"fmt"
|
2021-04-25 18:00:51 +02:00
|
|
|
"io"
|
2018-06-25 06:38:11 +02:00
|
|
|
h "net/http"
|
|
|
|
"net/http/httptest"
|
2018-08-25 23:05:18 +02:00
|
|
|
"os"
|
2018-10-01 21:52:16 +02:00
|
|
|
"path/filepath"
|
2018-09-08 21:33:46 +02:00
|
|
|
"strings"
|
2018-06-25 06:38:11 +02:00
|
|
|
"sync"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/goreleaser/goreleaser/internal/artifact"
|
2023-03-02 05:01:11 +02:00
|
|
|
"github.com/goreleaser/goreleaser/internal/testctx"
|
2018-08-15 04:50:20 +02:00
|
|
|
"github.com/goreleaser/goreleaser/pkg/config"
|
|
|
|
"github.com/goreleaser/goreleaser/pkg/context"
|
2018-11-16 21:18:37 +02:00
|
|
|
"github.com/stretchr/testify/require"
|
2018-06-25 06:38:11 +02:00
|
|
|
)
|
|
|
|
|
2018-08-25 23:05:18 +02:00
|
|
|
func TestAssetOpenDefault(t *testing.T) {
|
2021-04-25 19:20:49 +02:00
|
|
|
tf := filepath.Join(t.TempDir(), "asset")
|
|
|
|
require.NoError(t, os.WriteFile(tf, []byte("a"), 0o765))
|
2020-12-13 15:33:08 +02:00
|
|
|
|
2018-08-25 23:05:18 +02:00
|
|
|
a, err := assetOpenDefault("blah", &artifact.Artifact{
|
2020-12-13 15:33:08 +02:00
|
|
|
Path: tf,
|
2018-08-25 23:05:18 +02:00
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("can not open asset: %v", err)
|
|
|
|
}
|
2021-04-25 16:34:40 +02:00
|
|
|
t.Cleanup(func() {
|
|
|
|
require.NoError(t, a.ReadCloser.Close())
|
|
|
|
})
|
2021-04-25 18:00:51 +02:00
|
|
|
bs, err := io.ReadAll(a.ReadCloser)
|
2018-08-25 23:05:18 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("can not read asset: %v", err)
|
|
|
|
}
|
|
|
|
if string(bs) != "a" {
|
|
|
|
t.Fatalf("unexpected read content")
|
|
|
|
}
|
|
|
|
_, err = assetOpenDefault("blah", &artifact.Artifact{
|
|
|
|
Path: "blah",
|
|
|
|
})
|
|
|
|
if err == nil {
|
|
|
|
t.Fatalf("should fail on missing file")
|
|
|
|
}
|
|
|
|
_, err = assetOpenDefault("blah", &artifact.Artifact{
|
|
|
|
Path: os.TempDir(),
|
|
|
|
})
|
|
|
|
if err == nil {
|
|
|
|
t.Fatalf("should fail on existing dir")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-25 06:38:11 +02:00
|
|
|
func TestDefaults(t *testing.T) {
|
|
|
|
type args struct {
|
2019-11-18 15:34:17 +02:00
|
|
|
uploads []config.Upload
|
2018-06-25 06:38:11 +02:00
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
args args
|
|
|
|
wantErr bool
|
|
|
|
wantMode string
|
|
|
|
}{
|
2019-11-18 15:34:17 +02:00
|
|
|
{"set default", args{[]config.Upload{{Name: "a", Target: "http://"}}}, false, ModeArchive},
|
|
|
|
{"keep value", args{[]config.Upload{{Name: "a", Target: "http://...", Mode: ModeBinary}}}, false, ModeBinary},
|
2018-06-25 06:38:11 +02:00
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
2019-11-18 15:34:17 +02:00
|
|
|
if err := Defaults(tt.args.uploads); (err != nil) != tt.wantErr {
|
2018-06-25 06:38:11 +02:00
|
|
|
t.Errorf("Defaults() error = %v, wantErr %v", err, tt.wantErr)
|
|
|
|
}
|
2019-11-18 15:34:17 +02:00
|
|
|
if tt.wantMode != tt.args.uploads[0].Mode {
|
|
|
|
t.Errorf("Incorrect Defaults() mode %q , wanted %q", tt.args.uploads[0].Mode, tt.wantMode)
|
2018-06-25 06:38:11 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCheckConfig(t *testing.T) {
|
2023-03-02 05:01:11 +02:00
|
|
|
ctx := testctx.NewWithCfg(config.Project{
|
|
|
|
ProjectName: "blah",
|
|
|
|
Env: []string{"TEST_A_SECRET=x"},
|
|
|
|
})
|
2018-06-25 06:38:11 +02:00
|
|
|
type args struct {
|
|
|
|
ctx *context.Context
|
2019-11-18 15:34:17 +02:00
|
|
|
upload *config.Upload
|
2018-06-25 06:38:11 +02:00
|
|
|
kind string
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
args args
|
|
|
|
wantErr bool
|
|
|
|
}{
|
2019-11-18 15:34:17 +02:00
|
|
|
{"ok", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Username: "pepe", Mode: ModeArchive}, "test"}, false},
|
|
|
|
{"secret missing", args{ctx, &config.Upload{Name: "b", Target: "http://blabla", Username: "pepe", Mode: ModeArchive}, "test"}, true},
|
|
|
|
{"target missing", args{ctx, &config.Upload{Name: "a", Username: "pepe", Mode: ModeArchive}, "test"}, true},
|
|
|
|
{"name missing", args{ctx, &config.Upload{Target: "http://blabla", Username: "pepe", Mode: ModeArchive}, "test"}, true},
|
2021-02-12 21:01:06 +02:00
|
|
|
{"username missing", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Mode: ModeArchive}, "test"}, true},
|
|
|
|
{"username present", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Username: "pepe", Mode: ModeArchive}, "test"}, false},
|
2019-11-18 15:34:17 +02:00
|
|
|
{"mode missing", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Username: "pepe"}, "test"}, true},
|
|
|
|
{"mode invalid", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Username: "pepe", Mode: "blabla"}, "test"}, true},
|
|
|
|
{"cert invalid", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Username: "pepe", Mode: ModeBinary, TrustedCerts: "bad cert!"}, "test"}, true},
|
2018-06-25 06:38:11 +02:00
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
if err := CheckConfig(tt.args.ctx, tt.args.upload, tt.args.kind); (err != nil) != tt.wantErr {
|
|
|
|
t.Errorf("CheckConfig() error = %v, wantErr %v", err, tt.wantErr)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2021-02-12 21:01:06 +02:00
|
|
|
|
|
|
|
delete(ctx.Env, "TEST_A_SECRET")
|
|
|
|
|
|
|
|
tests = []struct {
|
|
|
|
name string
|
|
|
|
args args
|
|
|
|
wantErr bool
|
|
|
|
}{
|
|
|
|
{"username missing", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Mode: ModeArchive}, "test"}, false},
|
|
|
|
{"username present", args{ctx, &config.Upload{Name: "a", Target: "http://blabla", Username: "pepe", Mode: ModeArchive}, "test"}, true},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
if err := CheckConfig(tt.args.ctx, tt.args.upload, tt.args.kind); (err != nil) != tt.wantErr {
|
|
|
|
t.Errorf("CheckConfig() error = %v, wantErr %v", err, tt.wantErr)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2018-06-25 06:38:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type check struct {
|
|
|
|
path string
|
|
|
|
user string
|
|
|
|
pass string
|
|
|
|
content []byte
|
2018-10-01 21:52:16 +02:00
|
|
|
headers map[string]string
|
2018-06-25 06:38:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func checks(checks ...check) func(rs []*h.Request) error {
|
|
|
|
return func(rs []*h.Request) error {
|
|
|
|
for _, r := range rs {
|
|
|
|
found := false
|
|
|
|
for _, c := range checks {
|
|
|
|
if c.path == r.RequestURI {
|
|
|
|
found = true
|
|
|
|
err := doCheck(c, r)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !found {
|
2020-09-21 19:47:51 +02:00
|
|
|
return fmt.Errorf("check not found for request %+v", r)
|
2018-06-25 06:38:11 +02:00
|
|
|
}
|
|
|
|
}
|
2022-03-19 22:44:34 +02:00
|
|
|
if len(rs) != len(checks) {
|
|
|
|
return fmt.Errorf("expected %d requests, got %d", len(checks), len(rs))
|
|
|
|
}
|
2018-06-25 06:38:11 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func doCheck(c check, r *h.Request) error {
|
|
|
|
contentLength := int64(len(c.content))
|
|
|
|
if r.ContentLength != contentLength {
|
2020-09-21 19:47:51 +02:00
|
|
|
return fmt.Errorf("request content-length header value %v unexpected, wanted %v", r.ContentLength, contentLength)
|
2018-06-25 06:38:11 +02:00
|
|
|
}
|
2021-04-25 18:00:51 +02:00
|
|
|
bs, err := io.ReadAll(r.Body)
|
2018-06-25 06:38:11 +02:00
|
|
|
if err != nil {
|
2020-09-21 19:47:51 +02:00
|
|
|
return fmt.Errorf("reading request body: %v", err)
|
2018-06-25 06:38:11 +02:00
|
|
|
}
|
|
|
|
if !bytes.Equal(bs, c.content) {
|
|
|
|
return errors.New("content does not match")
|
|
|
|
}
|
|
|
|
if int64(len(bs)) != contentLength {
|
2020-09-21 19:47:51 +02:00
|
|
|
return fmt.Errorf("request content length %v unexpected, wanted %v", int64(len(bs)), contentLength)
|
2018-06-25 06:38:11 +02:00
|
|
|
}
|
|
|
|
if r.RequestURI != c.path {
|
2020-09-21 19:47:51 +02:00
|
|
|
return fmt.Errorf("bad request uri %q, expecting %q", r.RequestURI, c.path)
|
2018-06-25 06:38:11 +02:00
|
|
|
}
|
|
|
|
if u, p, ok := r.BasicAuth(); !ok || u != c.user || p != c.pass {
|
2020-09-21 19:47:51 +02:00
|
|
|
return fmt.Errorf("bad basic auth credentials: %s/%s", u, p)
|
2018-06-25 06:38:11 +02:00
|
|
|
}
|
2018-10-01 21:52:16 +02:00
|
|
|
for k, v := range c.headers {
|
|
|
|
if r.Header.Get(k) != v {
|
2020-09-21 19:47:51 +02:00
|
|
|
return fmt.Errorf("bad header value for %s: expected %s, got %s", k, v, r.Header.Get(k))
|
2018-10-01 21:52:16 +02:00
|
|
|
}
|
|
|
|
}
|
2018-06-25 06:38:11 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUpload(t *testing.T) {
|
|
|
|
content := []byte("blah!")
|
|
|
|
requests := []*h.Request{}
|
|
|
|
var m sync.Mutex
|
2018-09-08 21:33:46 +02:00
|
|
|
mux := h.NewServeMux()
|
2018-06-25 06:38:11 +02:00
|
|
|
mux.Handle("/", h.HandlerFunc(func(w h.ResponseWriter, r *h.Request) {
|
2021-04-25 18:00:51 +02:00
|
|
|
bs, err := io.ReadAll(r.Body)
|
2018-06-25 06:38:11 +02:00
|
|
|
if err != nil {
|
|
|
|
w.WriteHeader(h.StatusInternalServerError)
|
|
|
|
fmt.Fprintf(w, "reading request body: %v", err)
|
|
|
|
return
|
|
|
|
}
|
2021-04-25 18:00:51 +02:00
|
|
|
r.Body = io.NopCloser(bytes.NewReader(bs))
|
2018-06-25 06:38:11 +02:00
|
|
|
m.Lock()
|
|
|
|
requests = append(requests, r)
|
|
|
|
m.Unlock()
|
|
|
|
w.WriteHeader(h.StatusCreated)
|
|
|
|
w.Header().Set("Location", r.URL.RequestURI())
|
|
|
|
}))
|
|
|
|
assetOpen = func(k string, a *artifact.Artifact) (*asset, error) {
|
|
|
|
return &asset{
|
2021-04-25 18:00:51 +02:00
|
|
|
ReadCloser: io.NopCloser(bytes.NewReader(content)),
|
2018-06-25 06:38:11 +02:00
|
|
|
Size: int64(len(content)),
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
defer assetOpenReset()
|
2018-09-10 14:08:54 +02:00
|
|
|
var is2xx ResponseChecker = func(r *h.Response) error {
|
2018-06-25 06:38:11 +02:00
|
|
|
if r.StatusCode/100 == 2 {
|
2018-09-10 14:08:54 +02:00
|
|
|
return nil
|
2018-06-25 06:38:11 +02:00
|
|
|
}
|
2020-09-21 19:47:51 +02:00
|
|
|
return fmt.Errorf("unexpected http status code: %v", r.StatusCode)
|
2018-06-25 06:38:11 +02:00
|
|
|
}
|
2023-03-02 05:01:11 +02:00
|
|
|
ctx := testctx.NewWithCfg(config.Project{
|
2019-12-29 20:02:15 +02:00
|
|
|
ProjectName: "blah",
|
2023-03-02 05:01:11 +02:00
|
|
|
Env: []string{
|
|
|
|
"TEST_A_SECRET=x",
|
|
|
|
"TEST_A_USERNAME=u2",
|
|
|
|
},
|
|
|
|
}, testctx.WithVersion("2.1.0"))
|
2021-04-25 19:20:49 +02:00
|
|
|
folder := t.TempDir()
|
2018-06-25 06:38:11 +02:00
|
|
|
for _, a := range []struct {
|
|
|
|
ext string
|
|
|
|
typ artifact.Type
|
|
|
|
}{
|
|
|
|
{"---", artifact.DockerImage},
|
|
|
|
{"deb", artifact.LinuxPackage},
|
|
|
|
{"bin", artifact.Binary},
|
|
|
|
{"tar", artifact.UploadableArchive},
|
2024-01-29 21:29:49 +02:00
|
|
|
{"tar.gz", artifact.UploadableSourceArchive},
|
2018-06-25 06:38:11 +02:00
|
|
|
{"ubi", artifact.UploadableBinary},
|
|
|
|
{"sum", artifact.Checksum},
|
|
|
|
{"sig", artifact.Signature},
|
2021-11-12 03:56:03 +02:00
|
|
|
{"pem", artifact.Certificate},
|
2018-06-25 06:38:11 +02:00
|
|
|
} {
|
2021-04-25 19:20:49 +02:00
|
|
|
file := filepath.Join(folder, "a."+a.ext)
|
|
|
|
require.NoError(t, os.WriteFile(file, []byte("lorem ipsum"), 0o644))
|
2019-08-12 22:44:48 +02:00
|
|
|
ctx.Artifacts.Add(&artifact.Artifact{
|
2020-03-04 06:45:05 +02:00
|
|
|
Name: "a." + a.ext,
|
|
|
|
Goos: "linux",
|
|
|
|
Goarch: "amd64",
|
|
|
|
Path: file,
|
|
|
|
Type: a.typ,
|
2019-05-17 15:25:01 +02:00
|
|
|
Extra: map[string]interface{}{
|
2022-03-19 22:44:34 +02:00
|
|
|
artifact.ExtraID: "foo",
|
|
|
|
artifact.ExtraExt: a.ext,
|
2019-05-17 15:25:01 +02:00
|
|
|
},
|
|
|
|
})
|
2018-06-25 06:38:11 +02:00
|
|
|
}
|
2018-09-08 21:33:46 +02:00
|
|
|
|
2018-06-25 06:38:11 +02:00
|
|
|
tests := []struct {
|
2018-09-08 21:33:46 +02:00
|
|
|
name string
|
|
|
|
tryPlain bool
|
|
|
|
tryTLS bool
|
|
|
|
wantErrPlain bool
|
|
|
|
wantErrTLS bool
|
2019-11-18 15:34:17 +02:00
|
|
|
setup func(*httptest.Server) (*context.Context, config.Upload)
|
2018-09-08 21:33:46 +02:00
|
|
|
check func(r []*h.Request) error
|
2018-06-25 06:38:11 +02:00
|
|
|
}{
|
2021-04-25 19:20:49 +02:00
|
|
|
{
|
|
|
|
"wrong-mode", true, true, true, true,
|
2019-11-18 15:34:17 +02:00
|
|
|
func(s *httptest.Server) (*context.Context, config.Upload) {
|
|
|
|
return ctx, config.Upload{
|
2018-09-08 21:33:46 +02:00
|
|
|
Mode: "wrong-mode",
|
|
|
|
Name: "a",
|
|
|
|
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
|
|
|
Username: "u1",
|
|
|
|
TrustedCerts: cert(s),
|
|
|
|
}
|
|
|
|
},
|
2018-08-25 23:05:18 +02:00
|
|
|
checks(),
|
|
|
|
},
|
2021-04-25 19:20:49 +02:00
|
|
|
{
|
|
|
|
"username-from-env", true, true, false, false,
|
2019-11-18 15:34:17 +02:00
|
|
|
func(s *httptest.Server) (*context.Context, config.Upload) {
|
|
|
|
return ctx, config.Upload{
|
2018-09-08 21:33:46 +02:00
|
|
|
Mode: ModeArchive,
|
|
|
|
Name: "a",
|
|
|
|
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
|
|
|
TrustedCerts: cert(s),
|
|
|
|
}
|
|
|
|
},
|
2018-08-25 23:05:18 +02:00
|
|
|
checks(
|
2018-10-01 21:52:16 +02:00
|
|
|
check{"/blah/2.1.0/a.deb", "u2", "x", content, map[string]string{}},
|
|
|
|
check{"/blah/2.1.0/a.tar", "u2", "x", content, map[string]string{}},
|
2024-01-29 21:29:49 +02:00
|
|
|
check{"/blah/2.1.0/a.tar.gz", "u2", "x", content, map[string]string{}},
|
2018-08-25 23:05:18 +02:00
|
|
|
),
|
|
|
|
},
|
2021-04-25 19:20:49 +02:00
|
|
|
{
|
|
|
|
"post", true, true, false, false,
|
2019-11-18 15:34:17 +02:00
|
|
|
func(s *httptest.Server) (*context.Context, config.Upload) {
|
|
|
|
return ctx, config.Upload{
|
|
|
|
Method: h.MethodPost,
|
|
|
|
Mode: ModeArchive,
|
|
|
|
Name: "a",
|
|
|
|
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
|
|
|
Username: "u1",
|
|
|
|
TrustedCerts: cert(s),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
checks(
|
|
|
|
check{"/blah/2.1.0/a.deb", "u1", "x", content, map[string]string{}},
|
|
|
|
check{"/blah/2.1.0/a.tar", "u1", "x", content, map[string]string{}},
|
2024-01-29 21:29:49 +02:00
|
|
|
check{"/blah/2.1.0/a.tar.gz", "u1", "x", content, map[string]string{}},
|
2019-11-18 15:34:17 +02:00
|
|
|
),
|
|
|
|
},
|
2021-04-25 19:20:49 +02:00
|
|
|
{
|
|
|
|
"archive", true, true, false, false,
|
2019-11-18 15:34:17 +02:00
|
|
|
func(s *httptest.Server) (*context.Context, config.Upload) {
|
|
|
|
return ctx, config.Upload{
|
2018-09-08 21:33:46 +02:00
|
|
|
Mode: ModeArchive,
|
|
|
|
Name: "a",
|
|
|
|
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
|
|
|
Username: "u1",
|
|
|
|
TrustedCerts: cert(s),
|
|
|
|
}
|
|
|
|
},
|
2018-06-25 06:38:11 +02:00
|
|
|
checks(
|
2018-10-01 21:52:16 +02:00
|
|
|
check{"/blah/2.1.0/a.deb", "u1", "x", content, map[string]string{}},
|
|
|
|
check{"/blah/2.1.0/a.tar", "u1", "x", content, map[string]string{}},
|
2024-01-29 21:29:49 +02:00
|
|
|
check{"/blah/2.1.0/a.tar.gz", "u1", "x", content, map[string]string{}},
|
2018-06-25 06:38:11 +02:00
|
|
|
),
|
|
|
|
},
|
2021-04-25 19:20:49 +02:00
|
|
|
{
|
|
|
|
"archive_with_os_tmpl", true, true, false, false,
|
2020-03-04 06:45:05 +02:00
|
|
|
func(s *httptest.Server) (*context.Context, config.Upload) {
|
|
|
|
return ctx, config.Upload{
|
|
|
|
Mode: ModeArchive,
|
|
|
|
Name: "a",
|
|
|
|
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/{{.Os}}/{{.Arch}}",
|
|
|
|
Username: "u1",
|
|
|
|
TrustedCerts: cert(s),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
checks(
|
|
|
|
check{"/blah/2.1.0/linux/amd64/a.deb", "u1", "x", content, map[string]string{}},
|
|
|
|
check{"/blah/2.1.0/linux/amd64/a.tar", "u1", "x", content, map[string]string{}},
|
2024-01-29 21:29:49 +02:00
|
|
|
check{"/blah/2.1.0/linux/amd64/a.tar.gz", "u1", "x", content, map[string]string{}},
|
2020-03-04 06:45:05 +02:00
|
|
|
),
|
|
|
|
},
|
2021-04-25 19:20:49 +02:00
|
|
|
{
|
|
|
|
"archive_with_ids", true, true, false, false,
|
2019-11-18 15:34:17 +02:00
|
|
|
func(s *httptest.Server) (*context.Context, config.Upload) {
|
|
|
|
return ctx, config.Upload{
|
2019-05-17 15:25:01 +02:00
|
|
|
Mode: ModeArchive,
|
|
|
|
Name: "a",
|
|
|
|
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
|
|
|
Username: "u1",
|
|
|
|
TrustedCerts: cert(s),
|
|
|
|
IDs: []string{"foo"},
|
|
|
|
}
|
|
|
|
},
|
|
|
|
checks(
|
|
|
|
check{"/blah/2.1.0/a.deb", "u1", "x", content, map[string]string{}},
|
|
|
|
check{"/blah/2.1.0/a.tar", "u1", "x", content, map[string]string{}},
|
2024-01-29 21:29:49 +02:00
|
|
|
check{"/blah/2.1.0/a.tar.gz", "u1", "x", content, map[string]string{}},
|
2019-05-17 15:25:01 +02:00
|
|
|
),
|
|
|
|
},
|
2021-04-25 19:20:49 +02:00
|
|
|
{
|
|
|
|
"binary", true, true, false, false,
|
2019-11-18 15:34:17 +02:00
|
|
|
func(s *httptest.Server) (*context.Context, config.Upload) {
|
|
|
|
return ctx, config.Upload{
|
2018-09-08 21:33:46 +02:00
|
|
|
Mode: ModeBinary,
|
|
|
|
Name: "a",
|
|
|
|
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
|
|
|
Username: "u2",
|
|
|
|
TrustedCerts: cert(s),
|
|
|
|
}
|
|
|
|
},
|
2018-10-01 21:52:16 +02:00
|
|
|
checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content, map[string]string{}}),
|
2018-09-08 21:33:46 +02:00
|
|
|
},
|
2021-04-25 19:20:49 +02:00
|
|
|
{
|
|
|
|
"binary_with_os_tmpl", true, true, false, false,
|
2020-03-04 06:45:05 +02:00
|
|
|
func(s *httptest.Server) (*context.Context, config.Upload) {
|
|
|
|
return ctx, config.Upload{
|
|
|
|
Mode: ModeBinary,
|
|
|
|
Name: "a",
|
|
|
|
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/{{.Os}}/{{.Arch}}",
|
|
|
|
Username: "u2",
|
|
|
|
TrustedCerts: cert(s),
|
|
|
|
}
|
|
|
|
},
|
2023-06-06 16:46:02 +02:00
|
|
|
checks(check{"/blah/2.1.0/linux/amd64/a.ubi", "u2", "x", content, map[string]string{}}),
|
2020-03-04 06:45:05 +02:00
|
|
|
},
|
2021-04-25 19:20:49 +02:00
|
|
|
{
|
|
|
|
"binary_with_ids", true, true, false, false,
|
2019-11-18 15:34:17 +02:00
|
|
|
func(s *httptest.Server) (*context.Context, config.Upload) {
|
|
|
|
return ctx, config.Upload{
|
2019-05-17 15:25:01 +02:00
|
|
|
Mode: ModeBinary,
|
|
|
|
Name: "a",
|
|
|
|
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
|
|
|
Username: "u2",
|
|
|
|
TrustedCerts: cert(s),
|
|
|
|
IDs: []string{"foo"},
|
|
|
|
}
|
|
|
|
},
|
|
|
|
checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content, map[string]string{}}),
|
|
|
|
},
|
2021-04-25 19:20:49 +02:00
|
|
|
{
|
|
|
|
"binary-add-ending-bar", true, true, false, false,
|
2019-11-18 15:34:17 +02:00
|
|
|
func(s *httptest.Server) (*context.Context, config.Upload) {
|
|
|
|
return ctx, config.Upload{
|
2018-09-08 21:33:46 +02:00
|
|
|
Mode: ModeBinary,
|
|
|
|
Name: "a",
|
|
|
|
Target: s.URL + "/{{.ProjectName}}/{{.Version}}",
|
|
|
|
Username: "u2",
|
|
|
|
TrustedCerts: cert(s),
|
|
|
|
}
|
|
|
|
},
|
2018-10-01 21:52:16 +02:00
|
|
|
checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content, map[string]string{}}),
|
2018-06-25 06:38:11 +02:00
|
|
|
},
|
2021-04-25 19:20:49 +02:00
|
|
|
{
|
|
|
|
"archive-with-checksum-and-signature", true, true, false, false,
|
2019-11-18 15:34:17 +02:00
|
|
|
func(s *httptest.Server) (*context.Context, config.Upload) {
|
|
|
|
return ctx, config.Upload{
|
2018-09-08 21:33:46 +02:00
|
|
|
Mode: ModeArchive,
|
|
|
|
Name: "a",
|
|
|
|
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
|
|
|
Username: "u3",
|
|
|
|
Checksum: true,
|
|
|
|
Signature: true,
|
|
|
|
TrustedCerts: cert(s),
|
|
|
|
}
|
|
|
|
},
|
2018-06-25 06:38:11 +02:00
|
|
|
checks(
|
2018-10-01 21:52:16 +02:00
|
|
|
check{"/blah/2.1.0/a.deb", "u3", "x", content, map[string]string{}},
|
|
|
|
check{"/blah/2.1.0/a.tar", "u3", "x", content, map[string]string{}},
|
2024-01-29 21:29:49 +02:00
|
|
|
check{"/blah/2.1.0/a.tar.gz", "u3", "x", content, map[string]string{}},
|
2018-10-01 21:52:16 +02:00
|
|
|
check{"/blah/2.1.0/a.sum", "u3", "x", content, map[string]string{}},
|
|
|
|
check{"/blah/2.1.0/a.sig", "u3", "x", content, map[string]string{}},
|
2021-11-12 03:56:03 +02:00
|
|
|
check{"/blah/2.1.0/a.pem", "u3", "x", content, map[string]string{}},
|
2018-06-25 06:38:11 +02:00
|
|
|
),
|
|
|
|
},
|
2021-04-25 19:20:49 +02:00
|
|
|
{
|
|
|
|
"bad-template", true, true, true, true,
|
2019-11-18 15:34:17 +02:00
|
|
|
func(s *httptest.Server) (*context.Context, config.Upload) {
|
|
|
|
return ctx, config.Upload{
|
2018-09-08 21:33:46 +02:00
|
|
|
Mode: ModeBinary,
|
|
|
|
Name: "a",
|
|
|
|
Target: s.URL + "/{{.ProjectNameXXX}}/{{.VersionXXX}}/",
|
|
|
|
Username: "u3",
|
|
|
|
Checksum: true,
|
|
|
|
Signature: true,
|
|
|
|
TrustedCerts: cert(s),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
checks(),
|
|
|
|
},
|
2021-04-25 19:20:49 +02:00
|
|
|
{
|
|
|
|
"failed-request", true, true, true, true,
|
2019-11-18 15:34:17 +02:00
|
|
|
func(s *httptest.Server) (*context.Context, config.Upload) {
|
|
|
|
return ctx, config.Upload{
|
2018-09-08 21:33:46 +02:00
|
|
|
Mode: ModeBinary,
|
|
|
|
Name: "a",
|
|
|
|
Target: s.URL[0:strings.LastIndex(s.URL, ":")] + "/{{.ProjectName}}/{{.Version}}/",
|
|
|
|
Username: "u3",
|
|
|
|
Checksum: true,
|
|
|
|
Signature: true,
|
|
|
|
TrustedCerts: cert(s),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
checks(),
|
|
|
|
},
|
2021-04-25 19:20:49 +02:00
|
|
|
{
|
|
|
|
"broken-cert", false, true, false, true,
|
2019-11-18 15:34:17 +02:00
|
|
|
func(s *httptest.Server) (*context.Context, config.Upload) {
|
|
|
|
return ctx, config.Upload{
|
2018-09-08 21:33:46 +02:00
|
|
|
Mode: ModeBinary,
|
|
|
|
Name: "a",
|
|
|
|
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
|
|
|
Username: "u3",
|
|
|
|
Checksum: false,
|
|
|
|
Signature: false,
|
|
|
|
TrustedCerts: "bad certs!",
|
|
|
|
}
|
|
|
|
},
|
|
|
|
checks(),
|
|
|
|
},
|
2021-04-25 19:20:49 +02:00
|
|
|
{
|
|
|
|
"checksumheader", true, true, false, false,
|
2019-11-18 15:34:17 +02:00
|
|
|
func(s *httptest.Server) (*context.Context, config.Upload) {
|
|
|
|
return ctx, config.Upload{
|
2018-10-01 21:52:16 +02:00
|
|
|
Mode: ModeBinary,
|
|
|
|
Name: "a",
|
|
|
|
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
|
|
|
Username: "u2",
|
|
|
|
ChecksumHeader: "-x-sha256",
|
|
|
|
TrustedCerts: cert(s),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content, map[string]string{"-x-sha256": "5e2bf57d3f40c4b6df69daf1936cb766f832374b4fc0259a7cbff06e2f70f269"}}),
|
|
|
|
},
|
2021-04-25 19:20:49 +02:00
|
|
|
{
|
|
|
|
"custom-headers", true, true, false, false,
|
2021-01-07 19:15:53 +02:00
|
|
|
func(s *httptest.Server) (*context.Context, config.Upload) {
|
|
|
|
return ctx, config.Upload{
|
|
|
|
Mode: ModeBinary,
|
|
|
|
Name: "a",
|
|
|
|
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
|
|
|
Username: "u2",
|
|
|
|
CustomHeaders: map[string]string{
|
|
|
|
"x-custom-header-name": "custom-header-value",
|
|
|
|
},
|
|
|
|
TrustedCerts: cert(s),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content, map[string]string{"x-custom-header-name": "custom-header-value"}}),
|
|
|
|
},
|
2021-04-25 19:20:49 +02:00
|
|
|
{
|
|
|
|
"custom-headers-with-template", true, true, false, false,
|
2021-01-08 13:35:12 +02:00
|
|
|
func(s *httptest.Server) (*context.Context, config.Upload) {
|
|
|
|
return ctx, config.Upload{
|
|
|
|
Mode: ModeBinary,
|
|
|
|
Name: "a",
|
|
|
|
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
|
|
|
Username: "u2",
|
|
|
|
CustomHeaders: map[string]string{
|
|
|
|
"x-project-name": "{{ .ProjectName }}",
|
|
|
|
},
|
|
|
|
TrustedCerts: cert(s),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
checks(check{"/blah/2.1.0/a.ubi", "u2", "x", content, map[string]string{"x-project-name": "blah"}}),
|
|
|
|
},
|
2021-04-25 19:20:49 +02:00
|
|
|
{
|
|
|
|
"invalid-template-in-custom-headers", true, true, true, true,
|
2021-01-08 13:35:12 +02:00
|
|
|
func(s *httptest.Server) (*context.Context, config.Upload) {
|
|
|
|
return ctx, config.Upload{
|
|
|
|
Mode: ModeBinary,
|
|
|
|
Name: "a",
|
|
|
|
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
|
|
|
Username: "u2",
|
|
|
|
CustomHeaders: map[string]string{
|
|
|
|
"x-custom-header-name": "{{ .Env.NONEXISTINGVARIABLE and some bad expressions }}",
|
|
|
|
},
|
|
|
|
TrustedCerts: cert(s),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
checks(),
|
|
|
|
},
|
2022-03-19 22:44:34 +02:00
|
|
|
{
|
|
|
|
"filtering-by-ext", true, true, false, false,
|
|
|
|
func(s *httptest.Server) (*context.Context, config.Upload) {
|
|
|
|
return ctx, config.Upload{
|
|
|
|
Mode: ModeArchive,
|
|
|
|
Name: "a",
|
|
|
|
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
|
|
|
Username: "u3",
|
|
|
|
TrustedCerts: cert(s),
|
|
|
|
Exts: []string{"deb", "rpm"},
|
|
|
|
}
|
|
|
|
},
|
|
|
|
checks(
|
|
|
|
check{"/blah/2.1.0/a.deb", "u3", "x", content, map[string]string{}},
|
|
|
|
),
|
|
|
|
},
|
2022-08-12 14:44:54 +02:00
|
|
|
{
|
|
|
|
name: "given a server with ClientAuth = RequireAnyClientCert, " +
|
|
|
|
"and an Upload with ClientX509Cert and ClientX509Key set, " +
|
|
|
|
"then the response should pass",
|
|
|
|
tryTLS: true,
|
|
|
|
setup: func(s *httptest.Server) (*context.Context, config.Upload) {
|
|
|
|
s.TLS.ClientAuth = tls.RequireAnyClientCert
|
|
|
|
return ctx, config.Upload{
|
|
|
|
Mode: ModeArchive,
|
|
|
|
Name: "a",
|
|
|
|
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
|
|
|
Username: "u3",
|
|
|
|
TrustedCerts: cert(s),
|
|
|
|
ClientX509Cert: "testcert.pem",
|
|
|
|
ClientX509Key: "testkey.pem",
|
|
|
|
Exts: []string{"deb", "rpm"},
|
|
|
|
}
|
|
|
|
},
|
|
|
|
check: checks(
|
|
|
|
check{"/blah/2.1.0/a.deb", "u3", "x", content, map[string]string{}},
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "given a server with ClientAuth = RequireAnyClientCert, " +
|
|
|
|
"and an Upload without either ClientX509Cert or ClientX509Key set, " +
|
|
|
|
"then the response should fail",
|
|
|
|
tryTLS: true,
|
|
|
|
setup: func(s *httptest.Server) (*context.Context, config.Upload) {
|
|
|
|
s.TLS.ClientAuth = tls.RequireAnyClientCert
|
|
|
|
return ctx, config.Upload{
|
|
|
|
Mode: ModeArchive,
|
|
|
|
Name: "a",
|
|
|
|
Target: s.URL + "/{{.ProjectName}}/{{.Version}}/",
|
|
|
|
Username: "u3",
|
|
|
|
TrustedCerts: cert(s),
|
|
|
|
Exts: []string{"deb", "rpm"},
|
|
|
|
}
|
|
|
|
},
|
|
|
|
wantErrTLS: true,
|
|
|
|
check: checks(),
|
|
|
|
},
|
2018-06-25 06:38:11 +02:00
|
|
|
}
|
2018-09-08 21:33:46 +02:00
|
|
|
|
2019-11-18 15:34:17 +02:00
|
|
|
uploadAndCheck := func(t *testing.T, setup func(*httptest.Server) (*context.Context, config.Upload), wantErrPlain, wantErrTLS bool, check func(r []*h.Request) error, srv *httptest.Server) {
|
2021-01-15 14:54:31 +02:00
|
|
|
t.Helper()
|
2018-09-08 21:33:46 +02:00
|
|
|
requests = nil
|
2019-11-18 15:34:17 +02:00
|
|
|
ctx, upload := setup(srv)
|
2018-09-08 21:33:46 +02:00
|
|
|
wantErr := wantErrPlain
|
|
|
|
if srv.Certificate() != nil {
|
|
|
|
wantErr = wantErrTLS
|
|
|
|
}
|
2019-11-18 15:34:17 +02:00
|
|
|
if err := Upload(ctx, []config.Upload{upload}, "test", is2xx); (err != nil) != wantErr {
|
2018-09-08 21:33:46 +02:00
|
|
|
t.Errorf("Upload() error = %v, wantErr %v", err, wantErr)
|
|
|
|
}
|
|
|
|
if err := check(requests); err != nil {
|
|
|
|
t.Errorf("Upload() request invalid. Error: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-25 06:38:11 +02:00
|
|
|
for _, tt := range tests {
|
2022-08-12 14:44:54 +02:00
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
if tt.tryPlain {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
srv := httptest.NewServer(mux)
|
|
|
|
defer srv.Close()
|
|
|
|
uploadAndCheck(t, tt.setup, tt.wantErrPlain, tt.wantErrTLS, tt.check, srv)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
if tt.tryTLS {
|
|
|
|
t.Run(tt.name+"-tls", func(t *testing.T) {
|
|
|
|
srv := httptest.NewUnstartedServer(mux)
|
|
|
|
srv.StartTLS()
|
|
|
|
defer srv.Close()
|
|
|
|
uploadAndCheck(t, tt.setup, tt.wantErrPlain, tt.wantErrTLS, tt.check, srv)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
2018-09-08 21:33:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func cert(srv *httptest.Server) string {
|
|
|
|
if srv == nil || srv.Certificate() == nil {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
block := &pem.Block{
|
|
|
|
Type: "CERTIFICATE",
|
|
|
|
Bytes: srv.Certificate().Raw,
|
2018-06-25 06:38:11 +02:00
|
|
|
}
|
2018-09-08 21:33:46 +02:00
|
|
|
return string(pem.EncodeToMemory(block))
|
2018-06-25 06:38:11 +02:00
|
|
|
}
|