mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-08-16 12:16:36 +00:00
* s3api: load document-style policies from the advanced IAM config The advanced IAM file doubles as the S3 identity config when only -s3.iam.config is given. protojson drops its "document" field, so every policy landed with empty content and warned "skipping invalid policy" on each reload. Worse, if the same file also declares identities the empty content sticks in the policy map and fails the whole runtime policy sync into the IAM manager, so policies created later never reach it. * iam: skip an unparsable policy instead of failing the whole runtime sync One policy the engine cannot parse aborted SyncRuntimePolicies before it touched anything, so every other policy stayed unsynced and the engine kept serving whatever it last held. * s3api: reject a non-role RoleArn in AssumeRole as a bad request arn:aws:iam:::user/name can never resolve to a role, but the handler ran it through the trust-policy check and answered "not authorized to assume role", pointing the caller at a permission problem they do not have. * s3api: build the policy content before touching the entry Deleting "document" up front meant a marshal failure left the policy with neither field, so a later rewrite would emit it with no definition at all. * iam: pin the fail-closed handling of an unparsable policy Say in the comment that dropping it from the desired set deletes it from the engine on purpose, and cover it with a test. * s3api: widen the non-role RoleArn test to canonical ARN shapes The reported ARN omits the account id; a user ARN that carries one, and a non-principal ARN, must be rejected the same way.
84 lines
2.5 KiB
Go
84 lines
2.5 KiB
Go
package s3api
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"github.com/seaweedfs/seaweedfs/weed/filer"
|
|
"github.com/seaweedfs/seaweedfs/weed/pb/iam_pb"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// The advanced IAM file doubles as the S3 identity config when only
|
|
// -s3.iam.config is given, so its "document" policies must survive the parse.
|
|
func TestLoadAdvancedIAMConfigPolicyDocument(t *testing.T) {
|
|
config := []byte(`{
|
|
"sts": {"issuer": "seaweedfs-sts"},
|
|
"policies": [
|
|
{
|
|
"name": "ClientPolicy",
|
|
"document": {
|
|
"Version": "2012-10-17",
|
|
"Statement": [{"Effect": "Allow", "Action": ["s3:*"], "Resource": ["*"]}]
|
|
}
|
|
}
|
|
]
|
|
}`)
|
|
|
|
parsed := &iam_pb.S3ApiConfiguration{}
|
|
require.NoError(t, filer.ParseS3ConfigurationFromBytes(normalizeAdvancedIAMPolicies(config), parsed))
|
|
require.Len(t, parsed.Policies, 1)
|
|
require.Equal(t, "ClientPolicy", parsed.Policies[0].Name)
|
|
|
|
var document map[string]interface{}
|
|
require.NoError(t, json.Unmarshal([]byte(parsed.Policies[0].Content), &document))
|
|
require.Equal(t, "2012-10-17", document["Version"])
|
|
}
|
|
|
|
func TestNormalizeAdvancedIAMPolicies(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
name string
|
|
config string
|
|
content string
|
|
}{
|
|
{
|
|
name: "document object",
|
|
config: `{"policies":[{"name":"p","document":{"Version":"2012-10-17"}}]}`,
|
|
content: `{"Version":"2012-10-17"}`,
|
|
},
|
|
{
|
|
name: "document already encoded as a string",
|
|
config: `{"policies":[{"name":"p","document":"{\"Version\":\"2012-10-17\"}"}]}`,
|
|
content: `{"Version":"2012-10-17"}`,
|
|
},
|
|
{
|
|
name: "content wins over document",
|
|
config: `{"policies":[{"name":"p","content":"{\"Version\":\"keep\"}","document":{"Version":"drop"}}]}`,
|
|
content: `{"Version":"keep"}`,
|
|
},
|
|
{
|
|
name: "content only",
|
|
config: `{"policies":[{"name":"p","content":"{\"Version\":\"keep\"}"}]}`,
|
|
content: `{"Version":"keep"}`,
|
|
},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
parsed := &iam_pb.S3ApiConfiguration{}
|
|
require.NoError(t, filer.ParseS3ConfigurationFromBytes(normalizeAdvancedIAMPolicies([]byte(tc.config)), parsed))
|
|
require.Len(t, parsed.Policies, 1)
|
|
require.JSONEq(t, tc.content, parsed.Policies[0].Content)
|
|
})
|
|
}
|
|
}
|
|
|
|
// Anything that is not a policy list is handed to the proto parser untouched.
|
|
func TestNormalizeAdvancedIAMPoliciesLeavesOtherConfigsAlone(t *testing.T) {
|
|
for _, config := range []string{
|
|
`not json`,
|
|
`{"identities":[{"name":"admin"}]}`,
|
|
`{"policies":{"p":{"document":{}}}}`,
|
|
} {
|
|
require.Equal(t, config, string(normalizeAdvancedIAMPolicies([]byte(config))))
|
|
}
|
|
}
|