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.

414 lines
14 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. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  24. if errCode != s3err.ErrNone {
  25. return errCode
  26. }
  27. requestAccountId := getAccountId(r)
  28. if s3acl.ValidateAccount(requestAccountId, *bucketMetadata.Owner.ID) {
  29. return s3err.ErrNone
  30. }
  31. return s3err.ErrAccessDenied
  32. }
  33. //Check access for PutBucketAclHandler
  34. func (s3a *S3ApiServer) checkAccessForPutBucketAcl(requestAccountId, 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 s3acl.ValidateAccount(requestAccountId, *bucketMetadata.Owner.ID) {
  43. return bucketMetadata, s3err.ErrNone
  44. }
  45. if len(bucketMetadata.Acl) > 0 {
  46. reqGrants := s3acl.DetermineRequiredGrants(requestAccountId, 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", requestAccountId)
  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. // - ListMultipartUploadsHandler
  68. func (s3a *S3ApiServer) checkAccessForReadBucket(r *http.Request, bucket, aclAction string) (*BucketMetaData, s3err.ErrorCode) {
  69. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  70. if errCode != s3err.ErrNone {
  71. return nil, errCode
  72. }
  73. if bucketMetadata.ObjectOwnership == s3_constants.OwnershipBucketOwnerEnforced {
  74. return bucketMetadata, s3err.ErrNone
  75. }
  76. requestAccountId := s3acl.GetAccountId(r)
  77. if s3acl.ValidateAccount(requestAccountId, *bucketMetadata.Owner.ID) {
  78. return bucketMetadata, s3err.ErrNone
  79. }
  80. if len(bucketMetadata.Acl) > 0 {
  81. reqGrants := s3acl.DetermineRequiredGrants(requestAccountId, aclAction)
  82. for _, bucketGrant := range bucketMetadata.Acl {
  83. for _, reqGrant := range reqGrants {
  84. if s3acl.GrantEquals(bucketGrant, reqGrant) {
  85. return bucketMetadata, s3err.ErrNone
  86. }
  87. }
  88. }
  89. }
  90. glog.V(3).Infof("acl denied! request account id: %s", requestAccountId)
  91. return nil, s3err.ErrAccessDenied
  92. }
  93. //Check ObjectAcl-Read related access
  94. // includes:
  95. // - GetObjectAclHandler
  96. func (s3a *S3ApiServer) checkAccessForReadObjectAcl(r *http.Request, bucket, object string) (acp *s3.AccessControlPolicy, errCode s3err.ErrorCode) {
  97. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  98. if errCode != s3err.ErrNone {
  99. return nil, errCode
  100. }
  101. getAcpFunc := func() (*s3.AccessControlPolicy, s3err.ErrorCode) {
  102. entry, err := getObjectEntry(s3a, bucket, object)
  103. if err != nil {
  104. if err == filer_pb.ErrNotFound {
  105. return nil, s3err.ErrNoSuchKey
  106. } else {
  107. return nil, s3err.ErrInternalError
  108. }
  109. }
  110. if entry.IsDirectory {
  111. return nil, s3err.ErrExistingObjectIsDirectory
  112. }
  113. acpOwnerId := s3acl.GetAcpOwner(entry.Extended, *bucketMetadata.Owner.ID)
  114. acpOwnerName := s3a.accountManager.IdNameMapping[acpOwnerId]
  115. acpGrants := s3acl.GetAcpGrants(&acpOwnerId, entry.Extended)
  116. acp = &s3.AccessControlPolicy{
  117. Owner: &s3.Owner{
  118. ID: &acpOwnerId,
  119. DisplayName: &acpOwnerName,
  120. },
  121. Grants: acpGrants,
  122. }
  123. return acp, s3err.ErrNone
  124. }
  125. if bucketMetadata.ObjectOwnership == s3_constants.OwnershipBucketOwnerEnforced {
  126. return getAcpFunc()
  127. }
  128. requestAccountId := s3acl.GetAccountId(r)
  129. acp, errCode = getAcpFunc()
  130. if errCode != s3err.ErrNone {
  131. return nil, errCode
  132. }
  133. if s3acl.ValidateAccount(requestAccountId, *acp.Owner.ID) {
  134. return acp, s3err.ErrNone
  135. }
  136. if acp.Grants != nil {
  137. reqGrants := s3acl.DetermineRequiredGrants(requestAccountId, 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("CheckAccessForReadObjectAcl denied! request account id: %s", requestAccountId)
  147. return nil, s3err.ErrAccessDenied
  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. _, defaultErrorCode := s3a.checkAccessForReadBucket(r, bucket, s3_constants.PermissionRead)
  163. if defaultErrorCode != s3err.ErrNone {
  164. r.Header.Set(s3_constants.XSeaweedFSHeaderAmzBucketAccessDenied, "true")
  165. }
  166. r.Header.Set(s3_constants.XSeaweedFSHeaderAmzBucketOwnerId, *bucketMetadata.Owner.ID)
  167. }
  168. return s3err.ErrNone
  169. }
  170. // Check ObjectAcl-Write related access
  171. // includes:
  172. // - PutObjectAclHandler
  173. func (s3a *S3ApiServer) checkAccessForWriteObjectAcl(r *http.Request, bucket, object string) (*filer_pb.Entry, string, []*s3.Grant, s3err.ErrorCode) {
  174. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  175. if errCode != s3err.ErrNone {
  176. return nil, "", nil, errCode
  177. }
  178. requestAccountId := s3acl.GetAccountId(r)
  179. reqOwnerId, grants, errCode := s3acl.ExtractObjectAcl(r, s3a.accountManager, bucketMetadata.ObjectOwnership, *bucketMetadata.Owner.ID, requestAccountId, false)
  180. if errCode != s3err.ErrNone {
  181. return nil, "", nil, errCode
  182. }
  183. if bucketMetadata.ObjectOwnership == s3_constants.OwnershipBucketOwnerEnforced {
  184. return nil, "", nil, s3err.AccessControlListNotSupported
  185. }
  186. //object acl
  187. objectEntry, err := getObjectEntry(s3a, bucket, object)
  188. if err != nil {
  189. if err == filer_pb.ErrNotFound {
  190. return nil, "", nil, s3err.ErrNoSuchKey
  191. }
  192. return nil, "", nil, s3err.ErrInternalError
  193. }
  194. if objectEntry.IsDirectory {
  195. return nil, "", nil, s3err.ErrExistingObjectIsDirectory
  196. }
  197. objectOwner := s3acl.GetAcpOwner(objectEntry.Extended, *bucketMetadata.Owner.ID)
  198. //object owner is immutable
  199. if reqOwnerId != "" && reqOwnerId != objectOwner {
  200. return nil, "", nil, s3err.ErrAccessDenied
  201. }
  202. if s3acl.ValidateAccount(requestAccountId, objectOwner) {
  203. return objectEntry, objectOwner, grants, s3err.ErrNone
  204. }
  205. objectGrants := s3acl.GetAcpGrants(nil, objectEntry.Extended)
  206. if objectGrants != nil {
  207. requiredGrants := s3acl.DetermineRequiredGrants(requestAccountId, s3_constants.PermissionWriteAcp)
  208. for _, objectGrant := range objectGrants {
  209. for _, requiredGrant := range requiredGrants {
  210. if s3acl.GrantEquals(objectGrant, requiredGrant) {
  211. return objectEntry, objectOwner, grants, s3err.ErrNone
  212. }
  213. }
  214. }
  215. }
  216. glog.V(3).Infof("checkAccessForWriteObjectAcl denied! request account id: %s", requestAccountId)
  217. return nil, "", nil, s3err.ErrAccessDenied
  218. }
  219. func updateObjectEntry(s3a *S3ApiServer, bucket, object string, entry *filer_pb.Entry) error {
  220. dir, _ := filepath.Split(object)
  221. return s3a.updateEntry(util.Join(s3a.option.BucketsPath, bucket, dir), entry)
  222. }
  223. // CheckAccessForPutObject Check ACL for PutObject API
  224. // includes:
  225. // - PutObjectHandler
  226. func (s3a *S3ApiServer) CheckAccessForPutObject(r *http.Request, bucket, object string) s3err.ErrorCode {
  227. accountId := s3acl.GetAccountId(r)
  228. return s3a.checkAccessForWriteObject(r, bucket, object, accountId)
  229. }
  230. // CheckAccessForPutObjectPartHandler Check Acl for Upload object part
  231. // includes:
  232. // - PutObjectPartHandler
  233. func (s3a *S3ApiServer) CheckAccessForPutObjectPartHandler(r *http.Request, bucket string) s3err.ErrorCode {
  234. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  235. if errCode != s3err.ErrNone {
  236. return errCode
  237. }
  238. if bucketMetadata.ObjectOwnership == s3_constants.OwnershipBucketOwnerEnforced {
  239. return s3err.ErrNone
  240. }
  241. accountId := s3acl.GetAccountId(r)
  242. if !CheckBucketAccess(accountId, bucketMetadata, s3_constants.PermissionWrite) {
  243. return s3err.ErrAccessDenied
  244. }
  245. return s3err.ErrNone
  246. }
  247. // CheckAccessForNewMultipartUpload Check Acl for API
  248. // includes:
  249. // - NewMultipartUploadHandler
  250. func (s3a *S3ApiServer) CheckAccessForNewMultipartUpload(r *http.Request, bucket, object string) (s3err.ErrorCode, string) {
  251. accountId := s3acl.GetAccountId(r)
  252. if accountId == IdentityAnonymous.AccountId {
  253. return s3err.ErrAccessDenied, ""
  254. }
  255. errCode := s3a.checkAccessForWriteObject(r, bucket, object, accountId)
  256. return errCode, accountId
  257. }
  258. func (s3a *S3ApiServer) CheckAccessForAbortMultipartUpload(r *http.Request, bucket, object string) s3err.ErrorCode {
  259. return s3a.CheckAccessWithBucketOwnerAndInitiator(r, bucket, object)
  260. }
  261. func (s3a *S3ApiServer) CheckAccessForCompleteMultipartUpload(r *http.Request, bucket, object string) s3err.ErrorCode {
  262. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  263. if errCode != s3err.ErrNone {
  264. return errCode
  265. }
  266. if bucketMetadata.ObjectOwnership != s3_constants.OwnershipBucketOwnerEnforced {
  267. accountId := getAccountId(r)
  268. if !CheckBucketAccess(accountId, bucketMetadata, s3_constants.PermissionWrite) {
  269. return s3err.ErrAccessDenied
  270. }
  271. }
  272. return s3err.ErrNone
  273. }
  274. func (s3a *S3ApiServer) CheckAccessForListMultipartUploadParts(r *http.Request, bucket, object string) s3err.ErrorCode {
  275. return s3a.CheckAccessWithBucketOwnerAndInitiator(r, bucket, object)
  276. }
  277. // CheckAccessWithBucketOwnerAndInitiator Check Access Permission with 'bucketOwner' and 'multipartUpload initiator'
  278. func (s3a *S3ApiServer) CheckAccessWithBucketOwnerAndInitiator(r *http.Request, bucket, object string) s3err.ErrorCode {
  279. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  280. if errCode != s3err.ErrNone {
  281. return errCode
  282. }
  283. //bucket access allowed
  284. accountId := s3acl.GetAccountId(r)
  285. if s3acl.ValidateAccount(*bucketMetadata.Owner.ID, accountId) {
  286. return s3err.ErrNone
  287. }
  288. //multipart initiator allowed
  289. entry, err := getMultipartUpload(s3a, bucket, object)
  290. if err != nil {
  291. if err != filer_pb.ErrNotFound {
  292. return s3err.ErrInternalError
  293. }
  294. } else {
  295. uploadInitiator, ok := entry.Extended[s3_constants.ExtAmzMultipartInitiator]
  296. if !ok || accountId == string(uploadInitiator) {
  297. return s3err.ErrNone
  298. }
  299. }
  300. glog.V(3).Infof("CheckAccessWithBucketOwnerAndInitiator denied! request account id: %s", accountId)
  301. return s3err.ErrAccessDenied
  302. }
  303. func (s3a *S3ApiServer) checkAccessForWriteObject(r *http.Request, bucket, object, requestAccountId string) s3err.ErrorCode {
  304. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  305. if errCode != s3err.ErrNone {
  306. return errCode
  307. }
  308. requestOwnerId, grants, errCode := s3acl.ExtractObjectAcl(r, s3a.accountManager, bucketMetadata.ObjectOwnership, *bucketMetadata.Owner.ID, requestAccountId, true)
  309. if errCode != s3err.ErrNone {
  310. return errCode
  311. }
  312. if bucketMetadata.ObjectOwnership == s3_constants.OwnershipBucketOwnerEnforced {
  313. return s3err.ErrNone
  314. }
  315. if !CheckBucketAccess(requestAccountId, bucketMetadata, s3_constants.PermissionWrite) {
  316. return s3err.ErrAccessDenied
  317. }
  318. if requestOwnerId == "" {
  319. requestOwnerId = requestAccountId
  320. }
  321. entry, err := getObjectEntry(s3a, bucket, object)
  322. if err != nil {
  323. if err == filer_pb.ErrNotFound {
  324. s3acl.SetAcpOwnerHeader(r, requestOwnerId)
  325. s3acl.SetAcpGrantsHeader(r, grants)
  326. return s3err.ErrNone
  327. }
  328. return s3err.ErrInternalError
  329. }
  330. objectOwnerId := s3acl.GetAcpOwner(entry.Extended, *bucketMetadata.Owner.ID)
  331. //object owner is immutable
  332. if requestOwnerId != "" && objectOwnerId != requestOwnerId {
  333. return s3err.ErrAccessDenied
  334. }
  335. //Only the owner of the bucket and the owner of the object can overwrite the object
  336. if s3acl.ValidateAccount(requestOwnerId, objectOwnerId, *bucketMetadata.Owner.ID) {
  337. glog.V(3).Infof("checkAccessForWriteObject denied! request account id: %s, expect account id: %s", requestAccountId, *bucketMetadata.Owner.ID)
  338. return s3err.ErrAccessDenied
  339. }
  340. s3acl.SetAcpOwnerHeader(r, objectOwnerId)
  341. s3acl.SetAcpGrantsHeader(r, grants)
  342. return s3err.ErrNone
  343. }
  344. func CheckBucketAccess(requestAccountId string, bucketMetadata *BucketMetaData, permission string) bool {
  345. if s3acl.ValidateAccount(requestAccountId, *bucketMetadata.Owner.ID) {
  346. return true
  347. } else {
  348. if len(bucketMetadata.Acl) > 0 {
  349. reqGrants := s3acl.DetermineRequiredGrants(requestAccountId, permission)
  350. for _, bucketGrant := range bucketMetadata.Acl {
  351. for _, requiredGrant := range reqGrants {
  352. if s3acl.GrantEquals(bucketGrant, requiredGrant) {
  353. return true
  354. }
  355. }
  356. }
  357. }
  358. }
  359. glog.V(3).Infof("CheckBucketAccess denied! request account id: %s", requestAccountId)
  360. return false
  361. }
  362. func getObjectEntry(s3a *S3ApiServer, bucket, object string) (*filer_pb.Entry, error) {
  363. return s3a.getEntry(util.Join(s3a.option.BucketsPath, bucket), object)
  364. }
  365. func getMultipartUpload(s3a *S3ApiServer, bucket, object string) (*filer_pb.Entry, error) {
  366. return s3a.getEntry(s3a.genUploadsFolder(bucket), object)
  367. }