iamapi_test.go 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. package iamapi
  2. import (
  3. "encoding/xml"
  4. "net/http"
  5. "net/http/httptest"
  6. "net/url"
  7. "regexp"
  8. "testing"
  9. "github.com/aws/aws-sdk-go/aws"
  10. "github.com/aws/aws-sdk-go/aws/session"
  11. "github.com/aws/aws-sdk-go/service/iam"
  12. "github.com/gorilla/mux"
  13. "github.com/jinzhu/copier"
  14. "github.com/seaweedfs/seaweedfs/weed/pb/iam_pb"
  15. "github.com/seaweedfs/seaweedfs/weed/s3api/policy_engine"
  16. "github.com/stretchr/testify/assert"
  17. )
  18. var GetS3ApiConfiguration func(s3cfg *iam_pb.S3ApiConfiguration) (err error)
  19. var PutS3ApiConfiguration func(s3cfg *iam_pb.S3ApiConfiguration) (err error)
  20. var GetPolicies func(policies *Policies) (err error)
  21. var PutPolicies func(policies *Policies) (err error)
  22. var s3config = iam_pb.S3ApiConfiguration{}
  23. var policiesFile = Policies{Policies: make(map[string]policy_engine.PolicyDocument)}
  24. var ias = IamApiServer{s3ApiConfig: iamS3ApiConfigureMock{}}
  25. type iamS3ApiConfigureMock struct{}
  26. func (iam iamS3ApiConfigureMock) GetS3ApiConfiguration(s3cfg *iam_pb.S3ApiConfiguration) (err error) {
  27. _ = copier.Copy(&s3cfg.Identities, &s3config.Identities)
  28. return nil
  29. }
  30. func (iam iamS3ApiConfigureMock) PutS3ApiConfiguration(s3cfg *iam_pb.S3ApiConfiguration) (err error) {
  31. _ = copier.Copy(&s3config.Identities, &s3cfg.Identities)
  32. return nil
  33. }
  34. func (iam iamS3ApiConfigureMock) GetPolicies(policies *Policies) (err error) {
  35. _ = copier.Copy(&policies, &policiesFile)
  36. return nil
  37. }
  38. func (iam iamS3ApiConfigureMock) PutPolicies(policies *Policies) (err error) {
  39. _ = copier.Copy(&policiesFile, &policies)
  40. return nil
  41. }
  42. func TestCreateUser(t *testing.T) {
  43. userName := aws.String("Test")
  44. params := &iam.CreateUserInput{UserName: userName}
  45. req, _ := iam.New(session.New()).CreateUserRequest(params)
  46. _ = req.Build()
  47. out := CreateUserResponse{}
  48. response, err := executeRequest(req.HTTPRequest, out)
  49. assert.Equal(t, nil, err)
  50. assert.Equal(t, http.StatusOK, response.Code)
  51. //assert.Equal(t, out.XMLName, "lol")
  52. }
  53. func TestListUsers(t *testing.T) {
  54. params := &iam.ListUsersInput{}
  55. req, _ := iam.New(session.New()).ListUsersRequest(params)
  56. _ = req.Build()
  57. out := ListUsersResponse{}
  58. response, err := executeRequest(req.HTTPRequest, out)
  59. assert.Equal(t, nil, err)
  60. assert.Equal(t, http.StatusOK, response.Code)
  61. }
  62. func TestListAccessKeys(t *testing.T) {
  63. svc := iam.New(session.New())
  64. params := &iam.ListAccessKeysInput{}
  65. req, _ := svc.ListAccessKeysRequest(params)
  66. _ = req.Build()
  67. out := ListAccessKeysResponse{}
  68. response, err := executeRequest(req.HTTPRequest, out)
  69. assert.Equal(t, nil, err)
  70. assert.Equal(t, http.StatusOK, response.Code)
  71. }
  72. func TestGetUser(t *testing.T) {
  73. userName := aws.String("Test")
  74. params := &iam.GetUserInput{UserName: userName}
  75. req, _ := iam.New(session.New()).GetUserRequest(params)
  76. _ = req.Build()
  77. out := GetUserResponse{}
  78. response, err := executeRequest(req.HTTPRequest, out)
  79. assert.Equal(t, nil, err)
  80. assert.Equal(t, http.StatusOK, response.Code)
  81. }
  82. // Todo flat statement
  83. func TestCreatePolicy(t *testing.T) {
  84. params := &iam.CreatePolicyInput{
  85. PolicyName: aws.String("S3-read-only-example-bucket"),
  86. PolicyDocument: aws.String(`
  87. {
  88. "Version": "2012-10-17",
  89. "Statement": [
  90. {
  91. "Effect": "Allow",
  92. "Action": [
  93. "s3:Get*",
  94. "s3:List*"
  95. ],
  96. "Resource": [
  97. "arn:aws:s3:::EXAMPLE-BUCKET",
  98. "arn:aws:s3:::EXAMPLE-BUCKET/*"
  99. ]
  100. }
  101. ]
  102. }`),
  103. }
  104. req, _ := iam.New(session.New()).CreatePolicyRequest(params)
  105. _ = req.Build()
  106. out := CreatePolicyResponse{}
  107. response, err := executeRequest(req.HTTPRequest, out)
  108. assert.Equal(t, nil, err)
  109. assert.Equal(t, http.StatusOK, response.Code)
  110. }
  111. func TestPutUserPolicy(t *testing.T) {
  112. userName := aws.String("Test")
  113. params := &iam.PutUserPolicyInput{
  114. UserName: userName,
  115. PolicyName: aws.String("S3-read-only-example-bucket"),
  116. PolicyDocument: aws.String(
  117. `{
  118. "Version": "2012-10-17",
  119. "Statement": [
  120. {
  121. "Effect": "Allow",
  122. "Action": [
  123. "s3:Get*",
  124. "s3:List*"
  125. ],
  126. "Resource": [
  127. "arn:aws:s3:::EXAMPLE-BUCKET",
  128. "arn:aws:s3:::EXAMPLE-BUCKET/*"
  129. ]
  130. }
  131. ]
  132. }`),
  133. }
  134. req, _ := iam.New(session.New()).PutUserPolicyRequest(params)
  135. _ = req.Build()
  136. out := PutUserPolicyResponse{}
  137. response, err := executeRequest(req.HTTPRequest, out)
  138. assert.Equal(t, nil, err)
  139. assert.Equal(t, http.StatusOK, response.Code)
  140. }
  141. func TestPutUserPolicyError(t *testing.T) {
  142. userName := aws.String("InvalidUser")
  143. params := &iam.PutUserPolicyInput{
  144. UserName: userName,
  145. PolicyName: aws.String("S3-read-only-example-bucket"),
  146. PolicyDocument: aws.String(
  147. `{
  148. "Version": "2012-10-17",
  149. "Statement": [
  150. {
  151. "Effect": "Allow",
  152. "Action": [
  153. "s3:Get*",
  154. "s3:List*"
  155. ],
  156. "Resource": [
  157. "arn:aws:s3:::EXAMPLE-BUCKET",
  158. "arn:aws:s3:::EXAMPLE-BUCKET/*"
  159. ]
  160. }
  161. ]
  162. }`),
  163. }
  164. req, _ := iam.New(session.New()).PutUserPolicyRequest(params)
  165. _ = req.Build()
  166. response, err := executeRequest(req.HTTPRequest, nil)
  167. assert.Equal(t, nil, err)
  168. assert.Equal(t, http.StatusNotFound, response.Code)
  169. expectedMessage := "the user with name InvalidUser cannot be found"
  170. expectedCode := "NoSuchEntity"
  171. code, message := extractErrorCodeAndMessage(response)
  172. assert.Equal(t, expectedMessage, message)
  173. assert.Equal(t, expectedCode, code)
  174. }
  175. func extractErrorCodeAndMessage(response *httptest.ResponseRecorder) (string, string) {
  176. pattern := `<Error><Code>(.*)</Code><Message>(.*)</Message><Type>(.*)</Type></Error>`
  177. re := regexp.MustCompile(pattern)
  178. code := re.FindStringSubmatch(response.Body.String())[1]
  179. message := re.FindStringSubmatch(response.Body.String())[2]
  180. return code, message
  181. }
  182. func TestGetUserPolicy(t *testing.T) {
  183. userName := aws.String("Test")
  184. params := &iam.GetUserPolicyInput{UserName: userName, PolicyName: aws.String("S3-read-only-example-bucket")}
  185. req, _ := iam.New(session.New()).GetUserPolicyRequest(params)
  186. _ = req.Build()
  187. out := GetUserPolicyResponse{}
  188. response, err := executeRequest(req.HTTPRequest, out)
  189. assert.Equal(t, nil, err)
  190. assert.Equal(t, http.StatusOK, response.Code)
  191. }
  192. func TestUpdateUser(t *testing.T) {
  193. userName := aws.String("Test")
  194. newUserName := aws.String("Test-New")
  195. params := &iam.UpdateUserInput{NewUserName: newUserName, UserName: userName}
  196. req, _ := iam.New(session.New()).UpdateUserRequest(params)
  197. _ = req.Build()
  198. out := UpdateUserResponse{}
  199. response, err := executeRequest(req.HTTPRequest, out)
  200. assert.Equal(t, nil, err)
  201. assert.Equal(t, http.StatusOK, response.Code)
  202. }
  203. func TestDeleteUser(t *testing.T) {
  204. userName := aws.String("Test-New")
  205. params := &iam.DeleteUserInput{UserName: userName}
  206. req, _ := iam.New(session.New()).DeleteUserRequest(params)
  207. _ = req.Build()
  208. out := DeleteUserResponse{}
  209. response, err := executeRequest(req.HTTPRequest, out)
  210. assert.Equal(t, nil, err)
  211. assert.Equal(t, http.StatusOK, response.Code)
  212. }
  213. func executeRequest(req *http.Request, v interface{}) (*httptest.ResponseRecorder, error) {
  214. rr := httptest.NewRecorder()
  215. apiRouter := mux.NewRouter().SkipClean(true)
  216. apiRouter.Path("/").Methods(http.MethodPost).HandlerFunc(ias.DoActions)
  217. apiRouter.ServeHTTP(rr, req)
  218. return rr, xml.Unmarshal(rr.Body.Bytes(), &v)
  219. }
  220. func TestHandleImplicitUsername(t *testing.T) {
  221. var tests = []struct {
  222. r *http.Request
  223. values url.Values
  224. userName string
  225. }{
  226. {&http.Request{}, url.Values{}, ""},
  227. {&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"},
  228. {&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{}, ""},
  229. {&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{}, ""},
  230. {&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{}, ""},
  231. }
  232. for i, test := range tests {
  233. handleImplicitUsername(test.r, test.values)
  234. if un := test.values.Get("UserName"); un != test.userName {
  235. t.Errorf("No.%d: Got: %v, Expected: %v", i, un, test.userName)
  236. }
  237. }
  238. }