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.

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