mirror of
https://github.com/hanzos3/go.git
synced 2026-10-30 19:54:46 +00:00
hanzoai/* is for top-level products. A product's own SDK belongs in that
product's org, which is what zap-proto/{go,zip,http} and hanzo-ds/go already do
— this is the S3 SDK catching up, not a new convention.
Module path and every internal import rewritten; builds and tests unchanged.
Co-authored-by: Hanzo Dev <[email protected]>
461 lines
11 KiB
Go
461 lines
11 KiB
Go
/*
|
|
* MinIO Go Library for Amazon S3 Compatible Cloud Storage
|
|
* Copyright 2015-2023 MinIO, Inc.
|
|
*
|
|
* 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 minio
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/hanzos3/go/pkg/encrypt"
|
|
)
|
|
|
|
func TestPostPolicySetExpires(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input time.Time
|
|
wantErr bool
|
|
wantResult string
|
|
}{
|
|
{
|
|
name: "valid time",
|
|
input: time.Date(2023, time.March, 2, 15, 4, 5, 0, time.UTC),
|
|
wantErr: false,
|
|
wantResult: "2023-03-02T15:04:05",
|
|
},
|
|
{
|
|
name: "time before 1970",
|
|
input: time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC),
|
|
wantErr: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
pp := NewPostPolicy()
|
|
|
|
err := pp.SetExpires(tt.input)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("%s: want error: %v, got: %v", tt.name, tt.wantErr, err)
|
|
}
|
|
|
|
if tt.wantResult != "" {
|
|
result := pp.String()
|
|
if !strings.Contains(result, tt.wantResult) {
|
|
t.Errorf("%s: want result to contain: '%s', got: '%s'", tt.name, tt.wantResult, result)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPostPolicySetKey(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
wantErr bool
|
|
wantResult string
|
|
}{
|
|
{
|
|
name: "valid key",
|
|
input: "my-object",
|
|
wantResult: `"eq","$key","my-object"`,
|
|
},
|
|
{
|
|
name: "empty key",
|
|
input: "",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "key with spaces",
|
|
input: " ",
|
|
wantErr: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
pp := NewPostPolicy()
|
|
|
|
err := pp.SetKey(tt.input)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("%s: want error: %v, got: %v", tt.name, tt.wantErr, err)
|
|
}
|
|
|
|
if tt.wantResult != "" {
|
|
result := pp.String()
|
|
if !strings.Contains(result, tt.wantResult) {
|
|
t.Errorf("%s: want result to contain: '%s', got: '%s'", tt.name, tt.wantResult, result)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPostPolicySetKeyStartsWith(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
want string
|
|
}{
|
|
{
|
|
name: "valid key prefix",
|
|
input: "my-prefix/",
|
|
want: `["starts-with","$key","my-prefix/"]`,
|
|
},
|
|
{
|
|
name: "empty prefix (allow any key)",
|
|
input: "",
|
|
want: `["starts-with","$key",""]`,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
pp := NewPostPolicy()
|
|
|
|
err := pp.SetKeyStartsWith(tt.input)
|
|
if err != nil {
|
|
t.Errorf("%s: want no error, got: %v", tt.name, err)
|
|
}
|
|
|
|
if tt.want != "" {
|
|
result := pp.String()
|
|
if !strings.Contains(result, tt.want) {
|
|
t.Errorf("%s: want result to contain: '%s', got: '%s'", tt.name, tt.want, result)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPostPolicySetBucket(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
wantErr bool
|
|
wantResult string
|
|
}{
|
|
{
|
|
name: "valid bucket",
|
|
input: "my-bucket",
|
|
wantResult: `"eq","$bucket","my-bucket"`,
|
|
},
|
|
{
|
|
name: "empty bucket",
|
|
input: "",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "bucket with spaces",
|
|
input: " ",
|
|
wantErr: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
pp := NewPostPolicy()
|
|
|
|
err := pp.SetBucket(tt.input)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("%s: want error: %v, got: %v", tt.name, tt.wantErr, err)
|
|
}
|
|
|
|
if tt.wantResult != "" {
|
|
result := pp.String()
|
|
if !strings.Contains(result, tt.wantResult) {
|
|
t.Errorf("%s: want result to contain: '%s', got: '%s'", tt.name, tt.wantResult, result)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPostPolicySetCondition(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
matchType string
|
|
condition string
|
|
value string
|
|
wantErr bool
|
|
wantResult string
|
|
}{
|
|
{
|
|
name: "valid eq condition",
|
|
matchType: "eq",
|
|
condition: "X-Amz-Date",
|
|
value: "20210324T000000Z",
|
|
wantResult: `"eq","$X-Amz-Date","20210324T000000Z"`,
|
|
},
|
|
{
|
|
name: "empty value",
|
|
matchType: "eq",
|
|
condition: "X-Amz-Date",
|
|
value: "",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "invalid condition",
|
|
matchType: "eq",
|
|
condition: "Invalid-Condition",
|
|
value: "somevalue",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "valid starts-with condition",
|
|
matchType: "starts-with",
|
|
condition: "X-Amz-Credential",
|
|
value: "my-access-key",
|
|
wantResult: `"starts-with","$X-Amz-Credential","my-access-key"`,
|
|
},
|
|
{
|
|
name: "empty condition",
|
|
matchType: "eq",
|
|
condition: "",
|
|
value: "somevalue",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "empty matchType",
|
|
matchType: "",
|
|
condition: "X-Amz-Date",
|
|
value: "somevalue",
|
|
wantErr: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
pp := NewPostPolicy()
|
|
|
|
err := pp.SetCondition(tt.matchType, tt.condition, tt.value)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("%s: want error: %v, got: %v", tt.name, tt.wantErr, err)
|
|
}
|
|
|
|
if tt.wantResult != "" {
|
|
result := pp.String()
|
|
if !strings.Contains(result, tt.wantResult) {
|
|
t.Errorf("%s: want result to contain: '%s', got: '%s'", tt.name, tt.wantResult, result)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPostPolicySetTagging(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
tagging string
|
|
wantErr bool
|
|
wantResult string
|
|
}{
|
|
{
|
|
name: "valid tagging",
|
|
tagging: `<Tagging><TagSet><Tag><Key>key1</Key><Value>value1</Value></Tag></TagSet></Tagging>`,
|
|
wantResult: `"eq","$tagging","<Tagging><TagSet><Tag><Key>key1</Key><Value>value1</Value></Tag></TagSet></Tagging>"`,
|
|
},
|
|
{
|
|
name: "empty tagging",
|
|
tagging: "",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "whitespace tagging",
|
|
tagging: " ",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "invalid XML",
|
|
tagging: `<Tagging><TagSet><Tag><Key>key1</Key><Value>value1</Value></Tag></TagSet>`,
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "invalid schema",
|
|
tagging: `<InvalidTagging></InvalidTagging>`,
|
|
wantErr: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
pp := NewPostPolicy()
|
|
|
|
err := pp.SetTagging(tt.tagging)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("%s: want error: %v, got: %v", tt.name, tt.wantErr, err)
|
|
}
|
|
|
|
if tt.wantResult != "" {
|
|
result := pp.String()
|
|
if !strings.Contains(result, tt.wantResult) {
|
|
t.Errorf("%s: want result to contain: '%s', got: '%s'", tt.name, tt.wantResult, result)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPostPolicySetUserMetadata(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
key string
|
|
value string
|
|
wantErr bool
|
|
wantResult string
|
|
}{
|
|
{
|
|
name: "valid metadata",
|
|
key: "user-key",
|
|
value: "user-value",
|
|
wantResult: `"eq","$x-amz-meta-user-key","user-value"`,
|
|
},
|
|
{
|
|
name: "empty key",
|
|
key: "",
|
|
value: "somevalue",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "empty value",
|
|
key: "user-key",
|
|
value: "",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "key with spaces",
|
|
key: " ",
|
|
value: "somevalue",
|
|
wantErr: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
pp := NewPostPolicy()
|
|
|
|
err := pp.SetUserMetadata(tt.key, tt.value)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("%s: want error: %v, got: %v", tt.name, tt.wantErr, err)
|
|
}
|
|
|
|
if tt.wantResult != "" {
|
|
result := pp.String()
|
|
if !strings.Contains(result, tt.wantResult) {
|
|
t.Errorf("%s: want result to contain: '%s', got: '%s'", tt.name, tt.wantResult, result)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPostPolicySetChecksum(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
checksum Checksum
|
|
wantErr bool
|
|
wantResult string
|
|
}{
|
|
{
|
|
name: "valid checksum SHA256",
|
|
checksum: ChecksumSHA256.ChecksumBytes([]byte("somerandomdata")),
|
|
wantResult: `[["eq","$x-amz-checksum-algorithm","SHA256"],["eq","$x-amz-checksum-sha256","29/7Qm/iMzZ1O3zMbO0luv6mYWyS6JIqPYV9lc8w1PA="]]`,
|
|
},
|
|
{
|
|
name: "valid checksum CRC32",
|
|
checksum: ChecksumCRC32.ChecksumBytes([]byte("somerandomdata")),
|
|
wantResult: `[["eq","$x-amz-checksum-algorithm","CRC32"],["eq","$x-amz-checksum-crc32","7sOPnw=="]]`,
|
|
},
|
|
{
|
|
name: "empty checksum",
|
|
checksum: Checksum{},
|
|
wantResult: "",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
pp := NewPostPolicy()
|
|
|
|
err := pp.SetChecksum(tt.checksum)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("%s: want error: %v, got: %v", tt.name, tt.wantErr, err)
|
|
}
|
|
|
|
if tt.wantResult != "" {
|
|
result := pp.String()
|
|
if !strings.Contains(result, tt.wantResult) {
|
|
t.Errorf("%s: want result to contain: '%s', got: '%s'", tt.name, tt.wantResult, result)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPostPolicySetEncryption(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
sseType string
|
|
keyID string
|
|
want map[string]string
|
|
}{
|
|
{
|
|
name: "SSE-S3 encryption",
|
|
sseType: "SSE-S3",
|
|
keyID: "my-key-id",
|
|
want: map[string]string{
|
|
"X-Amz-Server-Side-Encryption": "aws:kms",
|
|
"X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id": "my-key-id",
|
|
},
|
|
},
|
|
{
|
|
name: "SSE-C encryption with Key ID",
|
|
sseType: "SSE-C",
|
|
keyID: "my-key-id",
|
|
want: map[string]string{
|
|
"X-Amz-Server-Side-Encryption-Customer-Key": "bXktc2VjcmV0LWtleTEyMzQ1Njc4OTBhYmNkZWZnaGk=",
|
|
"X-Amz-Server-Side-Encryption-Customer-Key-Md5": "T1mefJwyXBH43sRtfEgRZQ==",
|
|
"X-Amz-Server-Side-Encryption-Customer-Algorithm": "AES256",
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
pp := NewPostPolicy()
|
|
|
|
var sse encrypt.ServerSide
|
|
var err error
|
|
switch tt.sseType {
|
|
case "SSE-S3":
|
|
sse, err = encrypt.NewSSEKMS(tt.keyID, nil)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create SSE-KMS: %v", err)
|
|
}
|
|
case "SSE-C":
|
|
sse, err = encrypt.NewSSEC([]byte("my-secret-key1234567890abcdefghi"))
|
|
if err != nil {
|
|
t.Fatalf("Failed to create SSE-C: %v", err)
|
|
}
|
|
default:
|
|
t.Fatalf("Unknown SSE type: %s", tt.sseType)
|
|
}
|
|
|
|
pp.SetEncryption(sse)
|
|
|
|
for k, v := range tt.want {
|
|
if pp.formData[k] != v {
|
|
t.Errorf("%s: want %s: %s, got: %s", tt.name, k, v, pp.formData[k])
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|