You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							265 lines
						
					
					
						
							8.6 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							265 lines
						
					
					
						
							8.6 KiB
						
					
					
				| package iamapi | |
| 
 | |
| import ( | |
| 	"encoding/xml" | |
| 	"net/http" | |
| 	"net/http/httptest" | |
| 	"net/url" | |
| 	"regexp" | |
| 	"testing" | |
| 
 | |
| 	"github.com/aws/aws-sdk-go/aws" | |
| 	"github.com/aws/aws-sdk-go/aws/session" | |
| 	"github.com/aws/aws-sdk-go/service/iam" | |
| 	"github.com/gorilla/mux" | |
| 	"github.com/jinzhu/copier" | |
| 	"github.com/seaweedfs/seaweedfs/weed/pb/iam_pb" | |
| 	"github.com/seaweedfs/seaweedfs/weed/s3api/policy_engine" | |
| 	"github.com/stretchr/testify/assert" | |
| ) | |
| 
 | |
| var GetS3ApiConfiguration func(s3cfg *iam_pb.S3ApiConfiguration) (err error) | |
| var PutS3ApiConfiguration func(s3cfg *iam_pb.S3ApiConfiguration) (err error) | |
| var GetPolicies func(policies *Policies) (err error) | |
| var PutPolicies func(policies *Policies) (err error) | |
| 
 | |
| var s3config = iam_pb.S3ApiConfiguration{} | |
| var policiesFile = Policies{Policies: make(map[string]policy_engine.PolicyDocument)} | |
| var ias = IamApiServer{s3ApiConfig: iamS3ApiConfigureMock{}} | |
| 
 | |
| type iamS3ApiConfigureMock struct{} | |
| 
 | |
| func (iam iamS3ApiConfigureMock) GetS3ApiConfiguration(s3cfg *iam_pb.S3ApiConfiguration) (err error) { | |
| 	_ = copier.Copy(&s3cfg.Identities, &s3config.Identities) | |
| 	return nil | |
| } | |
| 
 | |
| func (iam iamS3ApiConfigureMock) PutS3ApiConfiguration(s3cfg *iam_pb.S3ApiConfiguration) (err error) { | |
| 	_ = copier.Copy(&s3config.Identities, &s3cfg.Identities) | |
| 	return nil | |
| } | |
| 
 | |
| func (iam iamS3ApiConfigureMock) GetPolicies(policies *Policies) (err error) { | |
| 	_ = copier.Copy(&policies, &policiesFile) | |
| 	return nil | |
| } | |
| 
 | |
| func (iam iamS3ApiConfigureMock) PutPolicies(policies *Policies) (err error) { | |
| 	_ = copier.Copy(&policiesFile, &policies) | |
| 	return nil | |
| } | |
| 
 | |
| func TestCreateUser(t *testing.T) { | |
| 	userName := aws.String("Test") | |
| 	params := &iam.CreateUserInput{UserName: userName} | |
| 	req, _ := iam.New(session.New()).CreateUserRequest(params) | |
| 	_ = req.Build() | |
| 	out := CreateUserResponse{} | |
| 	response, err := executeRequest(req.HTTPRequest, out) | |
| 	assert.Equal(t, nil, err) | |
| 	assert.Equal(t, http.StatusOK, response.Code) | |
| 	//assert.Equal(t, out.XMLName, "lol") | |
| } | |
| 
 | |
| func TestListUsers(t *testing.T) { | |
| 	params := &iam.ListUsersInput{} | |
| 	req, _ := iam.New(session.New()).ListUsersRequest(params) | |
| 	_ = req.Build() | |
| 	out := ListUsersResponse{} | |
| 	response, err := executeRequest(req.HTTPRequest, out) | |
| 	assert.Equal(t, nil, err) | |
| 	assert.Equal(t, http.StatusOK, response.Code) | |
| } | |
| 
 | |
| func TestListAccessKeys(t *testing.T) { | |
| 	svc := iam.New(session.New()) | |
| 	params := &iam.ListAccessKeysInput{} | |
| 	req, _ := svc.ListAccessKeysRequest(params) | |
| 	_ = req.Build() | |
| 	out := ListAccessKeysResponse{} | |
| 	response, err := executeRequest(req.HTTPRequest, out) | |
| 	assert.Equal(t, nil, err) | |
| 	assert.Equal(t, http.StatusOK, response.Code) | |
| } | |
| 
 | |
| func TestGetUser(t *testing.T) { | |
| 	userName := aws.String("Test") | |
| 	params := &iam.GetUserInput{UserName: userName} | |
| 	req, _ := iam.New(session.New()).GetUserRequest(params) | |
| 	_ = req.Build() | |
| 	out := GetUserResponse{} | |
| 	response, err := executeRequest(req.HTTPRequest, out) | |
| 	assert.Equal(t, nil, err) | |
| 	assert.Equal(t, http.StatusOK, response.Code) | |
| } | |
| 
 | |
| // Todo flat statement | |
| func TestCreatePolicy(t *testing.T) { | |
| 	params := &iam.CreatePolicyInput{ | |
| 		PolicyName: aws.String("S3-read-only-example-bucket"), | |
| 		PolicyDocument: aws.String(` | |
| 			{ | |
| 			  "Version": "2012-10-17", | |
| 			  "Statement": [ | |
| 				{ | |
| 				  "Effect": "Allow", | |
| 				  "Action": [ | |
| 					"s3:Get*", | |
| 					"s3:List*" | |
| 				  ], | |
| 				  "Resource": [ | |
| 					"arn:aws:s3:::EXAMPLE-BUCKET", | |
| 					"arn:aws:s3:::EXAMPLE-BUCKET/*" | |
| 				  ] | |
| 				} | |
| 			  ] | |
| 			}`), | |
| 	} | |
| 	req, _ := iam.New(session.New()).CreatePolicyRequest(params) | |
| 	_ = req.Build() | |
| 	out := CreatePolicyResponse{} | |
| 	response, err := executeRequest(req.HTTPRequest, out) | |
| 	assert.Equal(t, nil, err) | |
| 	assert.Equal(t, http.StatusOK, response.Code) | |
| } | |
| 
 | |
| func TestPutUserPolicy(t *testing.T) { | |
| 	userName := aws.String("Test") | |
| 	params := &iam.PutUserPolicyInput{ | |
| 		UserName:   userName, | |
| 		PolicyName: aws.String("S3-read-only-example-bucket"), | |
| 		PolicyDocument: aws.String( | |
| 			`{ | |
| 				  "Version": "2012-10-17", | |
| 				  "Statement": [ | |
| 					{ | |
| 					  "Effect": "Allow", | |
| 					  "Action": [ | |
| 						"s3:Get*", | |
| 						"s3:List*" | |
| 					  ], | |
| 					  "Resource": [ | |
| 						"arn:aws:s3:::EXAMPLE-BUCKET", | |
| 						"arn:aws:s3:::EXAMPLE-BUCKET/*" | |
| 					  ] | |
| 					} | |
| 				  ] | |
| 			}`), | |
| 	} | |
| 	req, _ := iam.New(session.New()).PutUserPolicyRequest(params) | |
| 	_ = req.Build() | |
| 	out := PutUserPolicyResponse{} | |
| 	response, err := executeRequest(req.HTTPRequest, out) | |
| 	assert.Equal(t, nil, err) | |
| 	assert.Equal(t, http.StatusOK, response.Code) | |
| } | |
| 
 | |
| func TestPutUserPolicyError(t *testing.T) { | |
| 	userName := aws.String("InvalidUser") | |
| 	params := &iam.PutUserPolicyInput{ | |
| 		UserName:   userName, | |
| 		PolicyName: aws.String("S3-read-only-example-bucket"), | |
| 		PolicyDocument: aws.String( | |
| 			`{ | |
| 				  "Version": "2012-10-17", | |
| 				  "Statement": [ | |
| 					{ | |
| 					  "Effect": "Allow", | |
| 					  "Action": [ | |
| 						"s3:Get*", | |
| 						"s3:List*" | |
| 					  ], | |
| 					  "Resource": [ | |
| 						"arn:aws:s3:::EXAMPLE-BUCKET", | |
| 						"arn:aws:s3:::EXAMPLE-BUCKET/*" | |
| 					  ] | |
| 					} | |
| 				  ] | |
| 			}`), | |
| 	} | |
| 	req, _ := iam.New(session.New()).PutUserPolicyRequest(params) | |
| 	_ = req.Build() | |
| 	response, err := executeRequest(req.HTTPRequest, nil) | |
| 	assert.Equal(t, nil, err) | |
| 	assert.Equal(t, http.StatusNotFound, response.Code) | |
| 
 | |
| 	expectedMessage := "the user with name InvalidUser cannot be found" | |
| 	expectedCode := "NoSuchEntity" | |
| 
 | |
| 	code, message := extractErrorCodeAndMessage(response) | |
| 
 | |
| 	assert.Equal(t, expectedMessage, message) | |
| 	assert.Equal(t, expectedCode, code) | |
| } | |
| 
 | |
| func extractErrorCodeAndMessage(response *httptest.ResponseRecorder) (string, string) { | |
| 	pattern := `<Error><Code>(.*)</Code><Message>(.*)</Message><Type>(.*)</Type></Error>` | |
| 	re := regexp.MustCompile(pattern) | |
| 
 | |
| 	code := re.FindStringSubmatch(response.Body.String())[1] | |
| 	message := re.FindStringSubmatch(response.Body.String())[2] | |
| 	return code, message | |
| } | |
| 
 | |
| func TestGetUserPolicy(t *testing.T) { | |
| 	userName := aws.String("Test") | |
| 	params := &iam.GetUserPolicyInput{UserName: userName, PolicyName: aws.String("S3-read-only-example-bucket")} | |
| 	req, _ := iam.New(session.New()).GetUserPolicyRequest(params) | |
| 	_ = req.Build() | |
| 	out := GetUserPolicyResponse{} | |
| 	response, err := executeRequest(req.HTTPRequest, out) | |
| 	assert.Equal(t, nil, err) | |
| 	assert.Equal(t, http.StatusOK, response.Code) | |
| } | |
| 
 | |
| func TestUpdateUser(t *testing.T) { | |
| 	userName := aws.String("Test") | |
| 	newUserName := aws.String("Test-New") | |
| 	params := &iam.UpdateUserInput{NewUserName: newUserName, UserName: userName} | |
| 	req, _ := iam.New(session.New()).UpdateUserRequest(params) | |
| 	_ = req.Build() | |
| 	out := UpdateUserResponse{} | |
| 	response, err := executeRequest(req.HTTPRequest, out) | |
| 	assert.Equal(t, nil, err) | |
| 	assert.Equal(t, http.StatusOK, response.Code) | |
| } | |
| 
 | |
| func TestDeleteUser(t *testing.T) { | |
| 	userName := aws.String("Test-New") | |
| 	params := &iam.DeleteUserInput{UserName: userName} | |
| 	req, _ := iam.New(session.New()).DeleteUserRequest(params) | |
| 	_ = req.Build() | |
| 	out := DeleteUserResponse{} | |
| 	response, err := executeRequest(req.HTTPRequest, out) | |
| 	assert.Equal(t, nil, err) | |
| 	assert.Equal(t, http.StatusOK, response.Code) | |
| } | |
| 
 | |
| func executeRequest(req *http.Request, v interface{}) (*httptest.ResponseRecorder, error) { | |
| 	rr := httptest.NewRecorder() | |
| 	apiRouter := mux.NewRouter().SkipClean(true) | |
| 	apiRouter.Path("/").Methods(http.MethodPost).HandlerFunc(ias.DoActions) | |
| 	apiRouter.ServeHTTP(rr, req) | |
| 	return rr, xml.Unmarshal(rr.Body.Bytes(), &v) | |
| } | |
| 
 | |
| func TestHandleImplicitUsername(t *testing.T) { | |
| 	var tests = []struct { | |
| 		r        *http.Request | |
| 		values   url.Values | |
| 		userName string | |
| 	}{ | |
| 		{&http.Request{}, url.Values{}, ""}, | |
| 		{&http.Request{Header: http.Header{"Authorization": []string{"AWS4-HMAC-SHA256 Credential=197FSAQ7HHTA48X64O3A/20220420/test1/iam/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=6757dc6b3d7534d67e17842760310e99ee695408497f6edc4fdb84770c252dc8"}}}, url.Values{}, "test1"}, | |
| 		{&http.Request{Header: http.Header{"Authorization": []string{"AWS4-HMAC-SHA256 =197FSAQ7HHTA48X64O3A/20220420/test1/iam/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=6757dc6b3d7534d67e17842760310e99ee695408497f6edc4fdb84770c252dc8"}}}, url.Values{}, ""}, | |
| 		{&http.Request{Header: http.Header{"Authorization": []string{"AWS4-HMAC-SHA256 Credential=197FSAQ7HHTA48X64O3A/20220420/test1/iam/aws4_request SignedHeaders=content-type;host;x-amz-date Signature=6757dc6b3d7534d67e17842760310e99ee695408497f6edc4fdb84770c252dc8"}}}, url.Values{}, ""}, | |
| 		{&http.Request{Header: http.Header{"Authorization": []string{"AWS4-HMAC-SHA256 Credential=197FSAQ7HHTA48X64O3A/20220420/test1/iam, SignedHeaders=content-type;host;x-amz-date, Signature=6757dc6b3d7534d67e17842760310e99ee695408497f6edc4fdb84770c252dc8"}}}, url.Values{}, ""}, | |
| 	} | |
| 
 | |
| 	for i, test := range tests { | |
| 		handleImplicitUsername(test.r, test.values) | |
| 		if un := test.values.Get("UserName"); un != test.userName { | |
| 			t.Errorf("No.%d: Got: %v, Expected: %v", i, un, test.userName) | |
| 		} | |
| 	} | |
| }
 |