From c851c0529c134021189ba7437dccd7a7fea22e65 Mon Sep 17 00:00:00 2001 From: Roman Loginov Date: Mon, 6 May 2024 20:34:49 +0300 Subject: [PATCH] [#112] Add integration test with bearer token Signed-off-by: Roman Loginov --- cmd/http-gw/integration_test.go | 94 +++++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 5 deletions(-) diff --git a/cmd/http-gw/integration_test.go b/cmd/http-gw/integration_test.go index f76c3ce..5d21094 100644 --- a/cmd/http-gw/integration_test.go +++ b/cmd/http-gw/integration_test.go @@ -6,25 +6,30 @@ import ( "archive/zip" "bytes" "context" + "encoding/base64" "encoding/json" "fmt" "io" "mime/multipart" "net/http" + "os" "sort" "testing" "time" containerv2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/pool" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/spf13/viper" "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" @@ -47,11 +52,17 @@ func TestIntegration(t *testing.T) { rootCtx := context.Background() aioImage := "truecloudlab/frostfs-aio:" versions := []string{ - "1.2.7", // frostfs-storage v0.36.0 RC + "1.2.7", + "1.3.0", } key, err := keys.NewPrivateKeyFromHex("1dd37fba80fec4e6a6f13fd708d8dcb3b29def768017052f6c930fa1c5d90bbb") require.NoError(t, err) + file, err := os.CreateTemp("", "wallet") + require.NoError(t, err) + defer os.Remove(file.Name()) + makeTempWallet(t, key, file.Name()) + var ownerID user.ID user.IDFromKey(&ownerID, key.PrivateKey.PublicKey) @@ -59,12 +70,16 @@ func TestIntegration(t *testing.T) { ctx, cancel2 := context.WithCancel(rootCtx) aioContainer := createDockerContainer(ctx, t, aioImage+version) - server, cancel := runServer() + server, cancel := runServer(file.Name()) clientPool := getPool(ctx, t, key) CID, err := createContainer(ctx, t, clientPool, ownerID, version) require.NoError(t, err, version) + token := makeBearerToken(t, key, ownerID, version) + t.Run("simple put "+version, func(t *testing.T) { simplePut(ctx, t, clientPool, CID, version) }) + t.Run("put with bearer token in header"+version, func(t *testing.T) { putWithBearerTokenInHeader(ctx, t, clientPool, CID, token) }) + t.Run("put with bearer token in cookie"+version, func(t *testing.T) { putWithBearerTokenInCookie(ctx, t, clientPool, CID, token) }) t.Run("put with duplicate keys "+version, func(t *testing.T) { putWithDuplicateKeys(t, CID) }) t.Run("simple get "+version, func(t *testing.T) { simpleGet(ctx, t, clientPool, ownerID, CID, version) }) t.Run("get by attribute "+version, func(t *testing.T) { getByAttr(ctx, t, clientPool, ownerID, CID, version) }) @@ -79,10 +94,13 @@ func TestIntegration(t *testing.T) { } } -func runServer() (App, context.CancelFunc) { +func runServer(pathToWallet string) (App, context.CancelFunc) { cancelCtx, cancel := context.WithCancel(context.Background()) v := getDefaultConfig() + v.Set(cfgWalletPath, pathToWallet) + v.Set(cfgWalletPassphrase, "") + l, lvl := newStdoutLogger(zapcore.DebugLevel) application := newApp(cancelCtx, WithConfig(v), WithLogger(l, lvl)) go application.Serve() @@ -98,7 +116,38 @@ func simplePut(ctx context.Context, t *testing.T, p *pool.Pool, CID cid.ID, vers makePutRequestAndCheck(ctx, t, p, CID, url) } +func putWithBearerTokenInHeader(ctx context.Context, t *testing.T, p *pool.Pool, CID cid.ID, token string) { + url := testHost + "/upload/" + CID.String() + + request, content, attributes := makePutRequest(t, url) + request.Header.Set("Authorization", "Bearer "+token) + resp, err := http.DefaultClient.Do(request) + require.NoError(t, err) + + checkPutResponse(ctx, t, p, CID, resp, content, attributes) +} + +func putWithBearerTokenInCookie(ctx context.Context, t *testing.T, p *pool.Pool, CID cid.ID, token string) { + url := testHost + "/upload/" + CID.String() + + request, content, attributes := makePutRequest(t, url) + request.AddCookie(&http.Cookie{Name: "Bearer", Value: token}) + resp, err := http.DefaultClient.Do(request) + require.NoError(t, err) + + checkPutResponse(ctx, t, p, CID, resp, content, attributes) +} + func makePutRequestAndCheck(ctx context.Context, t *testing.T, p *pool.Pool, cnrID cid.ID, url string) { + request, content, attributes := makePutRequest(t, url) + + resp, err := http.DefaultClient.Do(request) + require.NoError(t, err) + + checkPutResponse(ctx, t, p, cnrID, resp, content, attributes) +} + +func makePutRequest(t *testing.T, url string) (*http.Request, string, map[string]string) { content := "content of file" keyAttr, valAttr := "User-Attribute", "user value" attributes := map[string]string{ @@ -120,9 +169,10 @@ func makePutRequestAndCheck(ctx context.Context, t *testing.T, p *pool.Pool, cnr request.Header.Set("Content-Type", w.FormDataContentType()) request.Header.Set("X-Attribute-"+keyAttr, valAttr) - resp, err := http.DefaultClient.Do(request) - require.NoError(t, err) + return request, content, attributes +} +func checkPutResponse(ctx context.Context, t *testing.T, p *pool.Pool, cnrID cid.ID, resp *http.Response, content string, attributes map[string]string) { defer func() { err := resp.Body.Close() require.NoError(t, err) @@ -476,3 +526,37 @@ func putObject(ctx context.Context, t *testing.T, clientPool *pool.Pool, ownerID return id } + +func makeBearerToken(t *testing.T, key *keys.PrivateKey, ownerID user.ID, version string) string { + tkn := new(bearer.Token) + tkn.ForUser(ownerID) + tkn.SetExp(10000) + + if version == "1.2.7" { + tkn.SetEACLTable(*eacl.NewTable()) + } else { + tkn.SetImpersonate(true) + } + + err := tkn.Sign(key.PrivateKey) + require.NoError(t, err) + + t64 := base64.StdEncoding.EncodeToString(tkn.Marshal()) + require.NotEmpty(t, t64) + + return t64 +} + +func makeTempWallet(t *testing.T, key *keys.PrivateKey, path string) { + w, err := wallet.NewWallet(path) + require.NoError(t, err) + + acc := wallet.NewAccountFromPrivateKey(key) + err = acc.Encrypt("", w.Scrypt) + require.NoError(t, err) + + w.AddAccount(acc) + + err = w.Save() + require.NoError(t, err) +}