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.

360 lines
11 KiB

  1. package s3api
  2. import (
  3. "github.com/aws/aws-sdk-go/service/s3"
  4. "github.com/seaweedfs/seaweedfs/weed/glog"
  5. "github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
  6. "github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
  7. "github.com/seaweedfs/seaweedfs/weed/s3api/s3account"
  8. "github.com/seaweedfs/seaweedfs/weed/s3api/s3acl"
  9. "github.com/seaweedfs/seaweedfs/weed/s3api/s3err"
  10. "github.com/seaweedfs/seaweedfs/weed/util"
  11. "net/http"
  12. )
  13. func getAccountId(r *http.Request) string {
  14. id := r.Header.Get(s3_constants.AmzAccountId)
  15. if len(id) == 0 {
  16. return s3account.AccountAnonymous.Id
  17. } else {
  18. return id
  19. }
  20. }
  21. func (s3a *S3ApiServer) checkAccessByOwnership(r *http.Request, bucket string) s3err.ErrorCode {
  22. metadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  23. if errCode != s3err.ErrNone {
  24. return errCode
  25. }
  26. accountId := getAccountId(r)
  27. if accountId == s3account.AccountAdmin.Id || accountId == *metadata.Owner.ID {
  28. return s3err.ErrNone
  29. }
  30. return s3err.ErrAccessDenied
  31. }
  32. //Check access for PutBucketAclHandler
  33. func (s3a *S3ApiServer) checkAccessForPutBucketAcl(accountId, bucket string) (*BucketMetaData, s3err.ErrorCode) {
  34. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  35. if errCode != s3err.ErrNone {
  36. return nil, errCode
  37. }
  38. if bucketMetadata.ObjectOwnership == s3_constants.OwnershipBucketOwnerEnforced {
  39. return nil, s3err.AccessControlListNotSupported
  40. }
  41. if accountId == s3account.AccountAdmin.Id || accountId == *bucketMetadata.Owner.ID {
  42. return bucketMetadata, s3err.ErrNone
  43. }
  44. if len(bucketMetadata.Acl) > 0 {
  45. reqGrants := s3acl.DetermineReqGrants(accountId, s3_constants.PermissionWriteAcp)
  46. for _, bucketGrant := range bucketMetadata.Acl {
  47. for _, reqGrant := range reqGrants {
  48. if s3acl.GrantEquals(bucketGrant, reqGrant) {
  49. return bucketMetadata, s3err.ErrNone
  50. }
  51. }
  52. }
  53. }
  54. glog.V(3).Infof("acl denied! request account id: %s", accountId)
  55. return nil, s3err.ErrAccessDenied
  56. }
  57. func updateBucketEntry(s3a *S3ApiServer, entry *filer_pb.Entry) error {
  58. return s3a.updateEntry(s3a.option.BucketsPath, entry)
  59. }
  60. // Check Bucket/BucketAcl Read related access
  61. // includes:
  62. // - HeadBucketHandler
  63. // - GetBucketAclHandler
  64. // - ListObjectsV1Handler
  65. // - ListObjectsV2Handler
  66. func (s3a *S3ApiServer) checkAccessForReadBucket(r *http.Request, bucket, aclAction string) (*BucketMetaData, s3err.ErrorCode) {
  67. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  68. if errCode != s3err.ErrNone {
  69. return nil, errCode
  70. }
  71. if bucketMetadata.ObjectOwnership == s3_constants.OwnershipBucketOwnerEnforced {
  72. return bucketMetadata, s3err.ErrNone
  73. }
  74. accountId := s3acl.GetAccountId(r)
  75. if accountId == s3account.AccountAdmin.Id || accountId == *bucketMetadata.Owner.ID {
  76. return bucketMetadata, s3err.ErrNone
  77. }
  78. if len(bucketMetadata.Acl) > 0 {
  79. reqGrants := s3acl.DetermineReqGrants(accountId, aclAction)
  80. for _, bucketGrant := range bucketMetadata.Acl {
  81. for _, reqGrant := range reqGrants {
  82. if s3acl.GrantEquals(bucketGrant, reqGrant) {
  83. return bucketMetadata, s3err.ErrNone
  84. }
  85. }
  86. }
  87. }
  88. glog.V(3).Infof("acl denied! request account id: %s", accountId)
  89. return nil, s3err.ErrAccessDenied
  90. }
  91. //Check ObjectAcl-Read related access
  92. // includes:
  93. // - GetObjectAclHandler
  94. func (s3a *S3ApiServer) checkAccessForReadObjectAcl(r *http.Request, bucket, object string) (acp *s3.AccessControlPolicy, errCode s3err.ErrorCode) {
  95. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  96. if errCode != s3err.ErrNone {
  97. return nil, errCode
  98. }
  99. getAcpFunc := func() (*s3.AccessControlPolicy, s3err.ErrorCode) {
  100. entry, err := getObjectEntry(s3a, bucket, object)
  101. if err != nil {
  102. if err == filer_pb.ErrNotFound {
  103. return nil, s3err.ErrNoSuchKey
  104. } else {
  105. return nil, s3err.ErrInternalError
  106. }
  107. }
  108. if entry.IsDirectory {
  109. return nil, s3err.ErrExistingObjectIsDirectory
  110. }
  111. acpOwnerId := s3acl.GetAcpOwner(entry.Extended, *bucketMetadata.Owner.ID)
  112. acpOwnerName := s3a.accountManager.IdNameMapping[acpOwnerId]
  113. acpGrants := s3acl.GetAcpGrants(entry.Extended)
  114. acp = &s3.AccessControlPolicy{
  115. Owner: &s3.Owner{
  116. ID: &acpOwnerId,
  117. DisplayName: &acpOwnerName,
  118. },
  119. Grants: acpGrants,
  120. }
  121. return acp, s3err.ErrNone
  122. }
  123. if bucketMetadata.ObjectOwnership == s3_constants.OwnershipBucketOwnerEnforced {
  124. return getAcpFunc()
  125. } else {
  126. accountId := s3acl.GetAccountId(r)
  127. acp, errCode := getAcpFunc()
  128. if errCode != s3err.ErrNone {
  129. return nil, errCode
  130. }
  131. if accountId == *acp.Owner.ID {
  132. return acp, s3err.ErrNone
  133. }
  134. //find in Grants
  135. if acp.Grants != nil {
  136. reqGrants := s3acl.DetermineReqGrants(accountId, s3_constants.PermissionReadAcp)
  137. for _, requiredGrant := range reqGrants {
  138. for _, grant := range acp.Grants {
  139. if s3acl.GrantEquals(requiredGrant, grant) {
  140. return acp, s3err.ErrNone
  141. }
  142. }
  143. }
  144. }
  145. glog.V(3).Infof("acl denied! request account id: %s", accountId)
  146. return nil, s3err.ErrAccessDenied
  147. }
  148. }
  149. // Check Object-Read related access
  150. // includes:
  151. // - GetObjectHandler
  152. //
  153. // offload object access validation to Filer layer
  154. // - s3acl.CheckObjectAccessForReadObject
  155. func (s3a *S3ApiServer) checkBucketAccessForReadObject(r *http.Request, bucket string) s3err.ErrorCode {
  156. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  157. if errCode != s3err.ErrNone {
  158. return errCode
  159. }
  160. if bucketMetadata.ObjectOwnership != s3_constants.OwnershipBucketOwnerEnforced {
  161. //offload object acl validation to filer layer
  162. r.Header.Set(s3_constants.XSeaweedFSHeaderAmzBucketOwnerId, *bucketMetadata.Owner.ID)
  163. }
  164. return s3err.ErrNone
  165. }
  166. // Check ObjectAcl-Write related access
  167. // includes:
  168. // - PutObjectAclHandler
  169. func (s3a *S3ApiServer) checkAccessForWriteObjectAcl(accountId, bucket, object string) (bucketMetadata *BucketMetaData, objectEntry *filer_pb.Entry, objectOwner string, errCode s3err.ErrorCode) {
  170. bucketMetadata, errCode = s3a.bucketRegistry.GetBucketMetadata(bucket)
  171. if errCode != s3err.ErrNone {
  172. return nil, nil, "", errCode
  173. }
  174. if bucketMetadata.ObjectOwnership == s3_constants.OwnershipBucketOwnerEnforced {
  175. return nil, nil, "", s3err.AccessControlListNotSupported
  176. }
  177. //bucket acl
  178. bucketAclAllowed := false
  179. reqGrants := s3acl.DetermineReqGrants(accountId, s3_constants.PermissionWrite)
  180. if accountId == *bucketMetadata.Owner.ID {
  181. bucketAclAllowed = true
  182. } else if bucketMetadata.Acl != nil {
  183. bucketLoop:
  184. for _, bucketGrant := range bucketMetadata.Acl {
  185. for _, requiredGrant := range reqGrants {
  186. if s3acl.GrantEquals(bucketGrant, requiredGrant) {
  187. bucketAclAllowed = true
  188. break bucketLoop
  189. }
  190. }
  191. }
  192. }
  193. if !bucketAclAllowed {
  194. return nil, nil, "", s3err.ErrAccessDenied
  195. }
  196. //object acl
  197. objectEntry, err := getObjectEntry(s3a, bucket, object)
  198. if err != nil {
  199. if err == filer_pb.ErrNotFound {
  200. return nil, nil, "", s3err.ErrNoSuchKey
  201. }
  202. return nil, nil, "", s3err.ErrInternalError
  203. }
  204. if objectEntry.IsDirectory {
  205. return nil, nil, "", s3err.ErrExistingObjectIsDirectory
  206. }
  207. objectOwner = s3acl.GetAcpOwner(objectEntry.Extended, *bucketMetadata.Owner.ID)
  208. if accountId == objectOwner {
  209. return bucketMetadata, objectEntry, objectOwner, s3err.ErrNone
  210. }
  211. objectGrants := s3acl.GetAcpGrants(objectEntry.Extended)
  212. if objectGrants != nil {
  213. for _, objectGrant := range objectGrants {
  214. for _, requiredGrant := range reqGrants {
  215. if s3acl.GrantEquals(objectGrant, requiredGrant) {
  216. return bucketMetadata, objectEntry, objectOwner, s3err.ErrNone
  217. }
  218. }
  219. }
  220. }
  221. glog.V(3).Infof("acl denied! request account id: %s", accountId)
  222. return nil, nil, "", s3err.ErrAccessDenied
  223. }
  224. func updateObjectEntry(s3a *S3ApiServer, bucket string, entry *filer_pb.Entry) error {
  225. return s3a.updateEntry(util.Join(s3a.option.BucketsPath, bucket), entry)
  226. }
  227. // Check Object-Write related access
  228. // includes:
  229. // - PutObjectHandler
  230. // - PutObjectPartHandler
  231. func (s3a *S3ApiServer) checkAccessForWriteObject(r *http.Request, bucket, object string) s3err.ErrorCode {
  232. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  233. if errCode != s3err.ErrNone {
  234. return errCode
  235. }
  236. accountId := s3acl.GetAccountId(r)
  237. if bucketMetadata.ObjectOwnership == s3_constants.OwnershipBucketOwnerEnforced {
  238. // validate grants (only bucketOwnerFullControl acl is allowed)
  239. _, grants, errCode := s3acl.ParseAndValidateAclHeaders(r, s3a.accountManager, bucketMetadata.ObjectOwnership, *bucketMetadata.Owner.ID, accountId, false)
  240. if errCode != s3err.ErrNone {
  241. return errCode
  242. }
  243. if len(grants) > 1 {
  244. return s3err.AccessControlListNotSupported
  245. }
  246. bucketOwnerFullControlGrant := &s3.Grant{
  247. Permission: &s3_constants.PermissionFullControl,
  248. Grantee: &s3.Grantee{
  249. Type: &s3_constants.GrantTypeCanonicalUser,
  250. ID: bucketMetadata.Owner.ID,
  251. },
  252. }
  253. if len(grants) == 0 {
  254. // set default grants
  255. s3acl.SetAcpOwnerHeader(r, accountId)
  256. s3acl.SetAcpGrantsHeader(r, []*s3.Grant{bucketOwnerFullControlGrant})
  257. return s3err.ErrNone
  258. }
  259. if !s3acl.GrantEquals(bucketOwnerFullControlGrant, grants[0]) {
  260. return s3err.AccessControlListNotSupported
  261. }
  262. s3acl.SetAcpOwnerHeader(r, accountId)
  263. s3acl.SetAcpGrantsHeader(r, []*s3.Grant{bucketOwnerFullControlGrant})
  264. return s3err.ErrNone
  265. }
  266. //bucket access allowed
  267. bucketAclAllowed := false
  268. if accountId == *bucketMetadata.Owner.ID {
  269. bucketAclAllowed = true
  270. } else {
  271. if len(bucketMetadata.Acl) > 0 {
  272. reqGrants := s3acl.DetermineReqGrants(accountId, s3_constants.PermissionWrite)
  273. bucketLoop:
  274. for _, bucketGrant := range bucketMetadata.Acl {
  275. for _, requiredGrant := range reqGrants {
  276. if s3acl.GrantEquals(bucketGrant, requiredGrant) {
  277. bucketAclAllowed = true
  278. break bucketLoop
  279. }
  280. }
  281. }
  282. }
  283. }
  284. if !bucketAclAllowed {
  285. glog.V(3).Infof("acl denied! request account id: %s", accountId)
  286. return s3err.ErrAccessDenied
  287. }
  288. //object access allowed
  289. entry, err := getObjectEntry(s3a, bucket, object)
  290. if err != nil {
  291. if err != filer_pb.ErrNotFound {
  292. return s3err.ErrInternalError
  293. }
  294. } else {
  295. if entry.IsDirectory {
  296. return s3err.ErrExistingObjectIsDirectory
  297. }
  298. //Only the owner of the bucket and the owner of the object can overwrite the object
  299. objectOwner := s3acl.GetAcpOwner(entry.Extended, *bucketMetadata.Owner.ID)
  300. if accountId != objectOwner && accountId != *bucketMetadata.Owner.ID {
  301. glog.V(3).Infof("acl denied! request account id: %s, expect account id: %s", accountId, *bucketMetadata.Owner.ID)
  302. return s3err.ErrAccessDenied
  303. }
  304. }
  305. ownerId, grants, errCode := s3acl.ParseAndValidateAclHeadersOrElseDefault(r, s3a.accountManager, bucketMetadata.ObjectOwnership, *bucketMetadata.Owner.ID, accountId, false)
  306. if errCode != s3err.ErrNone {
  307. return errCode
  308. }
  309. s3acl.SetAcpOwnerHeader(r, ownerId)
  310. s3acl.SetAcpGrantsHeader(r, grants)
  311. return s3err.ErrNone
  312. }
  313. func getObjectEntry(s3a *S3ApiServer, bucket, object string) (*filer_pb.Entry, error) {
  314. return s3a.getEntry(util.Join(s3a.option.BucketsPath, bucket), object)
  315. }