2020-02-10 06:30:02 +08:00
|
|
|
package s3api
|
|
|
|
|
|
|
|
import (
|
2022-10-02 10:18:00 +08:00
|
|
|
"reflect"
|
2020-02-10 06:30:02 +08:00
|
|
|
"testing"
|
|
|
|
|
2024-05-17 19:54:09 +08:00
|
|
|
. "github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
|
2022-07-29 15:17:28 +08:00
|
|
|
"github.com/seaweedfs/seaweedfs/weed/pb/iam_pb"
|
2023-09-25 23:34:12 +08:00
|
|
|
jsonpb "google.golang.org/protobuf/encoding/protojson"
|
2020-02-10 06:30:02 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestIdentityListFileFormat(t *testing.T) {
|
|
|
|
|
2020-02-18 04:31:59 +08:00
|
|
|
s3ApiConfiguration := &iam_pb.S3ApiConfiguration{}
|
2020-02-10 06:30:02 +08:00
|
|
|
|
|
|
|
identity1 := &iam_pb.Identity{
|
|
|
|
Name: "some_name",
|
|
|
|
Credentials: []*iam_pb.Credential{
|
|
|
|
{
|
|
|
|
AccessKey: "some_access_key1",
|
|
|
|
SecretKey: "some_secret_key2",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Actions: []string{
|
|
|
|
ACTION_ADMIN,
|
|
|
|
ACTION_READ,
|
|
|
|
ACTION_WRITE,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
identity2 := &iam_pb.Identity{
|
|
|
|
Name: "some_read_only_user",
|
|
|
|
Credentials: []*iam_pb.Credential{
|
|
|
|
{
|
|
|
|
AccessKey: "some_access_key1",
|
|
|
|
SecretKey: "some_secret_key1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Actions: []string{
|
|
|
|
ACTION_READ,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
identity3 := &iam_pb.Identity{
|
|
|
|
Name: "some_normal_user",
|
|
|
|
Credentials: []*iam_pb.Credential{
|
|
|
|
{
|
|
|
|
AccessKey: "some_access_key2",
|
|
|
|
SecretKey: "some_secret_key2",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Actions: []string{
|
|
|
|
ACTION_READ,
|
|
|
|
ACTION_WRITE,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2020-02-18 04:31:59 +08:00
|
|
|
s3ApiConfiguration.Identities = append(s3ApiConfiguration.Identities, identity1)
|
|
|
|
s3ApiConfiguration.Identities = append(s3ApiConfiguration.Identities, identity2)
|
|
|
|
s3ApiConfiguration.Identities = append(s3ApiConfiguration.Identities, identity3)
|
2020-02-10 06:30:02 +08:00
|
|
|
|
2022-08-18 15:15:46 +08:00
|
|
|
m := jsonpb.MarshalOptions{
|
|
|
|
EmitUnpopulated: true,
|
|
|
|
Indent: " ",
|
2020-02-10 06:30:02 +08:00
|
|
|
}
|
|
|
|
|
2022-08-18 15:15:46 +08:00
|
|
|
text, _ := m.Marshal(s3ApiConfiguration)
|
2020-02-10 06:30:02 +08:00
|
|
|
|
2022-08-18 15:15:46 +08:00
|
|
|
println(string(text))
|
2020-02-10 06:30:02 +08:00
|
|
|
|
|
|
|
}
|
2022-01-04 07:39:36 +08:00
|
|
|
|
|
|
|
func TestCanDo(t *testing.T) {
|
|
|
|
ident1 := &Identity{
|
|
|
|
Name: "anything",
|
|
|
|
Actions: []Action{
|
|
|
|
"Write:bucket1/a/b/c/*",
|
|
|
|
"Write:bucket1/a/b/other",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
// object specific
|
2022-01-04 13:05:20 +08:00
|
|
|
assert.Equal(t, true, ident1.canDo(ACTION_WRITE, "bucket1", "/a/b/c/d.txt"))
|
2024-05-17 19:54:09 +08:00
|
|
|
assert.Equal(t, false, ident1.canDo(ACTION_DELETE_BUCKET, "bucket1", ""))
|
2022-01-04 13:05:20 +08:00
|
|
|
assert.Equal(t, false, ident1.canDo(ACTION_WRITE, "bucket1", "/a/b/other/some"), "action without *")
|
2022-01-04 07:39:36 +08:00
|
|
|
|
|
|
|
// bucket specific
|
|
|
|
ident2 := &Identity{
|
|
|
|
Name: "anything",
|
|
|
|
Actions: []Action{
|
|
|
|
"Read:bucket1",
|
|
|
|
"Write:bucket1/*",
|
2023-09-22 05:07:04 +08:00
|
|
|
"WriteAcp:bucket1",
|
2022-01-04 07:39:36 +08:00
|
|
|
},
|
|
|
|
}
|
2022-01-04 13:05:20 +08:00
|
|
|
assert.Equal(t, true, ident2.canDo(ACTION_READ, "bucket1", "/a/b/c/d.txt"))
|
|
|
|
assert.Equal(t, true, ident2.canDo(ACTION_WRITE, "bucket1", "/a/b/c/d.txt"))
|
2023-09-22 05:07:04 +08:00
|
|
|
assert.Equal(t, true, ident2.canDo(ACTION_WRITE_ACP, "bucket1", ""))
|
|
|
|
assert.Equal(t, false, ident2.canDo(ACTION_READ_ACP, "bucket1", ""))
|
2022-01-04 13:05:20 +08:00
|
|
|
assert.Equal(t, false, ident2.canDo(ACTION_LIST, "bucket1", "/a/b/c/d.txt"))
|
2022-01-04 07:39:36 +08:00
|
|
|
|
|
|
|
// across buckets
|
|
|
|
ident3 := &Identity{
|
|
|
|
Name: "anything",
|
|
|
|
Actions: []Action{
|
|
|
|
"Read",
|
|
|
|
"Write",
|
|
|
|
},
|
|
|
|
}
|
2022-01-04 13:05:20 +08:00
|
|
|
assert.Equal(t, true, ident3.canDo(ACTION_READ, "bucket1", "/a/b/c/d.txt"))
|
|
|
|
assert.Equal(t, true, ident3.canDo(ACTION_WRITE, "bucket1", "/a/b/c/d.txt"))
|
|
|
|
assert.Equal(t, false, ident3.canDo(ACTION_LIST, "bucket1", "/a/b/other/some"))
|
2023-09-22 05:07:04 +08:00
|
|
|
assert.Equal(t, false, ident3.canDo(ACTION_WRITE_ACP, "bucket1", ""))
|
2022-01-04 07:39:36 +08:00
|
|
|
|
|
|
|
// partial buckets
|
|
|
|
ident4 := &Identity{
|
|
|
|
Name: "anything",
|
|
|
|
Actions: []Action{
|
|
|
|
"Read:special_*",
|
2023-09-22 05:07:04 +08:00
|
|
|
"ReadAcp:special_*",
|
2022-01-04 07:39:36 +08:00
|
|
|
},
|
|
|
|
}
|
2022-01-04 13:05:20 +08:00
|
|
|
assert.Equal(t, true, ident4.canDo(ACTION_READ, "special_bucket", "/a/b/c/d.txt"))
|
2023-09-22 05:07:04 +08:00
|
|
|
assert.Equal(t, true, ident4.canDo(ACTION_READ_ACP, "special_bucket", ""))
|
2022-01-04 13:05:20 +08:00
|
|
|
assert.Equal(t, false, ident4.canDo(ACTION_READ, "bucket1", "/a/b/c/d.txt"))
|
2022-01-04 07:39:36 +08:00
|
|
|
|
2022-01-12 19:04:59 +08:00
|
|
|
// admin buckets
|
|
|
|
ident5 := &Identity{
|
|
|
|
Name: "anything",
|
|
|
|
Actions: []Action{
|
|
|
|
"Admin:special_*",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
assert.Equal(t, true, ident5.canDo(ACTION_READ, "special_bucket", "/a/b/c/d.txt"))
|
2023-09-22 05:07:04 +08:00
|
|
|
assert.Equal(t, true, ident5.canDo(ACTION_READ_ACP, "special_bucket", ""))
|
2022-01-12 19:04:59 +08:00
|
|
|
assert.Equal(t, true, ident5.canDo(ACTION_WRITE, "special_bucket", "/a/b/c/d.txt"))
|
2023-09-22 05:07:04 +08:00
|
|
|
assert.Equal(t, true, ident5.canDo(ACTION_WRITE_ACP, "special_bucket", ""))
|
2023-09-21 23:19:11 +08:00
|
|
|
|
|
|
|
// anonymous buckets
|
|
|
|
ident6 := &Identity{
|
|
|
|
Name: "anonymous",
|
|
|
|
Actions: []Action{
|
|
|
|
"Read",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
assert.Equal(t, true, ident6.canDo(ACTION_READ, "anything_bucket", "/a/b/c/d.txt"))
|
2024-05-17 19:54:09 +08:00
|
|
|
|
|
|
|
//test deleteBucket operation
|
|
|
|
ident7 := &Identity{
|
|
|
|
Name: "anything",
|
|
|
|
Actions: []Action{
|
|
|
|
"DeleteBucket:bucket1",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
assert.Equal(t, true, ident7.canDo(ACTION_DELETE_BUCKET, "bucket1", ""))
|
2022-10-02 10:18:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
type LoadS3ApiConfigurationTestCase struct {
|
2023-09-25 23:34:12 +08:00
|
|
|
pbAccount *iam_pb.Account
|
2022-10-02 10:18:00 +08:00
|
|
|
pbIdent *iam_pb.Identity
|
|
|
|
expectIdent *Identity
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestLoadS3ApiConfiguration(t *testing.T) {
|
2023-09-25 23:34:12 +08:00
|
|
|
specifiedAccount := Account{
|
|
|
|
Id: "specifiedAccountID",
|
|
|
|
DisplayName: "specifiedAccountName",
|
|
|
|
EmailAddress: "specifiedAccounEmail@example.com",
|
|
|
|
}
|
|
|
|
pbSpecifiedAccount := iam_pb.Account{
|
|
|
|
Id: "specifiedAccountID",
|
|
|
|
DisplayName: "specifiedAccountName",
|
|
|
|
EmailAddress: "specifiedAccounEmail@example.com",
|
|
|
|
}
|
2022-10-02 10:18:00 +08:00
|
|
|
testCases := map[string]*LoadS3ApiConfigurationTestCase{
|
|
|
|
"notSpecifyAccountId": {
|
|
|
|
pbIdent: &iam_pb.Identity{
|
|
|
|
Name: "notSpecifyAccountId",
|
|
|
|
Actions: []string{
|
|
|
|
"Read",
|
|
|
|
"Write",
|
|
|
|
},
|
|
|
|
Credentials: []*iam_pb.Credential{
|
|
|
|
{
|
|
|
|
AccessKey: "some_access_key1",
|
|
|
|
SecretKey: "some_secret_key2",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectIdent: &Identity{
|
2023-09-25 23:34:12 +08:00
|
|
|
Name: "notSpecifyAccountId",
|
|
|
|
Account: &AccountAdmin,
|
2022-10-02 10:18:00 +08:00
|
|
|
Actions: []Action{
|
|
|
|
"Read",
|
|
|
|
"Write",
|
|
|
|
},
|
|
|
|
Credentials: []*Credential{
|
|
|
|
{
|
|
|
|
AccessKey: "some_access_key1",
|
|
|
|
SecretKey: "some_secret_key2",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"specifiedAccountID": {
|
2023-09-25 23:34:12 +08:00
|
|
|
pbAccount: &pbSpecifiedAccount,
|
2022-10-02 10:18:00 +08:00
|
|
|
pbIdent: &iam_pb.Identity{
|
2023-09-25 23:34:12 +08:00
|
|
|
Name: "specifiedAccountID",
|
|
|
|
Account: &pbSpecifiedAccount,
|
2022-10-02 10:18:00 +08:00
|
|
|
Actions: []string{
|
|
|
|
"Read",
|
|
|
|
"Write",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectIdent: &Identity{
|
2023-09-25 23:34:12 +08:00
|
|
|
Name: "specifiedAccountID",
|
|
|
|
Account: &specifiedAccount,
|
2022-10-02 10:18:00 +08:00
|
|
|
Actions: []Action{
|
|
|
|
"Read",
|
|
|
|
"Write",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"anonymous": {
|
|
|
|
pbIdent: &iam_pb.Identity{
|
|
|
|
Name: "anonymous",
|
|
|
|
Actions: []string{
|
|
|
|
"Read",
|
|
|
|
"Write",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectIdent: &Identity{
|
2023-09-25 23:34:12 +08:00
|
|
|
Name: "anonymous",
|
|
|
|
Account: &AccountAnonymous,
|
2022-10-02 10:18:00 +08:00
|
|
|
Actions: []Action{
|
|
|
|
"Read",
|
|
|
|
"Write",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
config := &iam_pb.S3ApiConfiguration{
|
|
|
|
Identities: make([]*iam_pb.Identity, 0),
|
|
|
|
}
|
|
|
|
for _, v := range testCases {
|
|
|
|
config.Identities = append(config.Identities, v.pbIdent)
|
2023-09-25 23:34:12 +08:00
|
|
|
if v.pbAccount != nil {
|
|
|
|
config.Accounts = append(config.Accounts, v.pbAccount)
|
|
|
|
}
|
2022-10-02 10:18:00 +08:00
|
|
|
}
|
2022-01-12 19:04:59 +08:00
|
|
|
|
2022-10-02 10:18:00 +08:00
|
|
|
iam := IdentityAccessManagement{}
|
|
|
|
err := iam.loadS3ApiConfiguration(config)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, ident := range iam.identities {
|
|
|
|
tc := testCases[ident.Name]
|
|
|
|
if !reflect.DeepEqual(ident, tc.expectIdent) {
|
2023-09-25 23:34:12 +08:00
|
|
|
t.Errorf("not expect for ident name %s", ident.Name)
|
2022-10-02 10:18:00 +08:00
|
|
|
}
|
|
|
|
}
|
2022-01-04 07:39:36 +08:00
|
|
|
}
|