cubefs/objectnode/auth_form_test.go
yhjiango 4401624f96 feat(objectnode): s3 sts and signature auth
1. sts federation token
2. signature auth code refactor

Signed-off-by: yhjiango <jiangyunhua@oppo.com>
2023-08-30 20:05:32 +08:00

212 lines
6.7 KiB
Go

// Copyright 2023 The CubeFS Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package objectnode
import (
"bytes"
"encoding/base64"
"mime/multipart"
"net/http/httptest"
"strings"
"testing"
"time"
"github.com/stretchr/testify/require"
)
func TestNewFormAuthWithV2(t *testing.T) {
now := time.Now().UTC()
datetime := now.Format(ISO8601Format)
accessKey := "AKIAIOSN7EXAMPLE"
policyStr := `{
"expiration": "2333-12-30T12:00:00.000Z",
"conditions": [{"bucket": "cfsexamplebucket"}]
}`
policy := base64.StdEncoding.EncodeToString([]byte(policyStr))
var buf bytes.Buffer
w := multipart.NewWriter(&buf)
fw, _ := w.CreateFormField(AWSAccessKeyID)
fw.Write([]byte(accessKey))
fw, _ = w.CreateFormField("key")
fw.Write([]byte("test.txt"))
fw, _ = w.CreateFormField("Policy")
fw.Write([]byte(policy))
fw, _ = w.CreateFormField(Signature)
fw.Write([]byte("signature"))
w.Close()
request := httptest.NewRequest("POST", "http://s3.cubefs.com/bucket", &buf)
request.Header.Set(ContentType, w.FormDataContentType())
request.Header.Set(Date, datetime)
require.NoError(t, request.ParseMultipartForm(8<<20))
fa, err := NewFormAuth(request)
require.NoError(t, err)
require.False(t, fa.IsPresigned())
require.False(t, fa.IsExpired())
require.False(t, fa.IsSkewed())
require.Empty(t, fa.SignedHeaders())
require.Equal(t, "signature", fa.Signature())
require.Equal(t, signatureV2, fa.Version())
require.Equal(t, signV2Algorithm, fa.Algorithm())
cred := fa.Credential()
require.Empty(t, cred.Region)
require.Empty(t, cred.Service)
require.Empty(t, cred.Request)
require.Empty(t, cred.Date)
require.Empty(t, cred.Expires)
require.Equal(t, datetime, cred.TimeStamp)
require.Equal(t, accessKey, cred.AccessKey)
}
func TestNewFormAuthWithV4(t *testing.T) {
now := time.Now().UTC()
date := now.Format(DateLayout)
datetime := now.Format(ISO8601Format)
accessKey := "AKIAIOSN7EXAMPLE"
region := "cn-south-1"
service := "s3"
awsRequest := "aws4_request"
policyStr := `{
"expiration": "2333-12-30T12:00:00.000Z",
"conditions": [{"bucket": "cfsexamplebucket"}]
}`
policy := base64.StdEncoding.EncodeToString([]byte(policyStr))
var buf bytes.Buffer
w := multipart.NewWriter(&buf)
fw, _ := w.CreateFormField(XAmzAlgorithm)
fw.Write([]byte(signV4Algorithm))
fw, _ = w.CreateFormField(XAmzCredential)
fw.Write([]byte(strings.Join([]string{accessKey, date, region, service, awsRequest}, "/")))
fw, _ = w.CreateFormField(XAmzDate)
fw.Write([]byte(datetime))
fw, _ = w.CreateFormField("Policy")
fw.Write([]byte(policy))
fw, _ = w.CreateFormField(XAmzSignature)
fw.Write([]byte("signature"))
w.Close()
request := httptest.NewRequest("POST", "http://s3.cubefs.com/bucket", &buf)
request.Header.Set(ContentType, w.FormDataContentType())
require.NoError(t, request.ParseMultipartForm(8<<20))
fa, err := NewFormAuth(request)
require.NoError(t, err)
require.False(t, fa.IsPresigned())
require.False(t, fa.IsExpired())
require.False(t, fa.IsSkewed())
require.Empty(t, fa.SignedHeaders())
require.Equal(t, "signature", fa.Signature())
require.Equal(t, signatureV4, fa.Version())
require.Equal(t, signV4Algorithm, fa.Algorithm())
cred := fa.Credential()
require.Empty(t, cred.Expires)
require.Equal(t, region, cred.Region)
require.Equal(t, service, cred.Service)
require.Equal(t, awsRequest, cred.Request)
require.Equal(t, date, cred.Date)
require.Equal(t, datetime, cred.TimeStamp)
require.Equal(t, accessKey, cred.AccessKey)
}
func TestFormAuthV2SignatureMatch(t *testing.T) {
policyStr := `{
"expiration": "2333-12-30T12:00:00.000Z",
"conditions": [
{"bucket": "cfsexamplebucket"},
["starts-with", "$key", "user/eric/"],
{"acl": "public-read"},
["starts-with", "$Content-Type", "image/"],
{"x-amz-meta-uuid": "14365123651274"},
["starts-with", "$x-amz-meta-tag", ""]
]
}`
policy := base64.StdEncoding.EncodeToString([]byte(policyStr))
secretKey := "SKIAIOSN7EXAMPLEcfsCUBEFSEXAMPLE"
signature := calculateSignatureV2(secretKey, policy)
var buf bytes.Buffer
w := multipart.NewWriter(&buf)
fw, _ := w.CreateFormField(AWSAccessKeyID)
fw.Write([]byte("AKIAIOSFODNN7EXAMPLE"))
fw, _ = w.CreateFormField("Policy")
fw.Write([]byte(policy))
fw, _ = w.CreateFormField("key")
fw.Write([]byte("user/eric/test.txt"))
fw, _ = w.CreateFormField(Signature)
fw.Write([]byte(signature))
w.Close()
request := httptest.NewRequest("POST", "http://s3.cubefs.com/bucket", &buf)
request.Header.Set(ContentType, w.FormDataContentType())
request.Header.Set(Date, time.Now().UTC().Format(ISO8601Format))
require.NoError(t, request.ParseMultipartForm(8<<20))
fa, err := NewFormAuth(request)
require.NoError(t, err)
require.True(t, fa.SignatureMatch(secretKey, nil))
}
func TestFormAuthV4SignatureMatch(t *testing.T) {
policyStr := `{
"expiration": "2333-12-30T12:00:00.000Z",
"conditions": [
{"bucket": "cfsexamplebucket"},
["starts-with", "$key", "user/eric/"],
{"acl": "public-read"},
["starts-with", "$Content-Type", "image/"],
{"x-amz-meta-uuid": "14365123651274"},
["starts-with", "$x-amz-meta-tag", ""]
]
}`
policy := base64.StdEncoding.EncodeToString([]byte(policyStr))
now := time.Now().UTC()
date := now.Format(DateLayout)
datetime := now.Format(ISO8601Format)
accessKey := "AKIAIOSN7EXAMPLE"
secretKey := "SKIAIOSN7EXAMPLEcfsCUBEFSEXAMPLE"
region := "cn-south-1"
service := "s3"
awsRequest := "aws4_request"
signingKey := buildSigningKey(signatureV4, secretKey, date, region, service, awsRequest)
signature := calculateSignature(signingKey, policy)
var buf bytes.Buffer
w := multipart.NewWriter(&buf)
fw, _ := w.CreateFormField(XAmzAlgorithm)
fw.Write([]byte(signV4Algorithm))
fw, _ = w.CreateFormField(XAmzCredential)
fw.Write([]byte(strings.Join([]string{accessKey, date, region, service, awsRequest}, "/")))
fw, _ = w.CreateFormField(XAmzDate)
fw.Write([]byte(datetime))
fw, _ = w.CreateFormField("Policy")
fw.Write([]byte(policy))
fw, _ = w.CreateFormField(XAmzSignature)
fw.Write([]byte(signature))
w.Close()
request := httptest.NewRequest("POST", "http://s3.cubefs.com/bucket", &buf)
request.Header.Set(ContentType, w.FormDataContentType())
require.NoError(t, request.ParseMultipartForm(8<<20))
fa, err := NewFormAuth(request)
require.NoError(t, err)
require.True(t, fa.SignatureMatch(secretKey, nil))
}