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.

406 lines
13 KiB

5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
  1. package s3api
  2. import (
  3. "net/http"
  4. "path/filepath"
  5. "github.com/aws/aws-sdk-go/service/s3"
  6. "github.com/seaweedfs/seaweedfs/weed/glog"
  7. "github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
  8. "github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
  9. "github.com/seaweedfs/seaweedfs/weed/s3api/s3acl"
  10. "github.com/seaweedfs/seaweedfs/weed/s3api/s3err"
  11. "github.com/seaweedfs/seaweedfs/weed/util"
  12. )
  13. func (s3a *S3ApiServer) checkAccessByOwnership(r *http.Request, bucket string) s3err.ErrorCode {
  14. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  15. if errCode != s3err.ErrNone {
  16. return errCode
  17. }
  18. requestAccountId := s3acl.GetAccountId(r)
  19. if s3acl.ValidateAccount(requestAccountId, *bucketMetadata.Owner.ID) {
  20. return s3err.ErrNone
  21. }
  22. return s3err.ErrAccessDenied
  23. }
  24. // Check access for PutBucketAclHandler
  25. func (s3a *S3ApiServer) checkAccessForPutBucketAcl(requestAccountId, bucket string) (*BucketMetaData, s3err.ErrorCode) {
  26. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  27. if errCode != s3err.ErrNone {
  28. return nil, errCode
  29. }
  30. if bucketMetadata.ObjectOwnership == s3_constants.OwnershipBucketOwnerEnforced {
  31. return nil, s3err.AccessControlListNotSupported
  32. }
  33. if s3acl.ValidateAccount(requestAccountId, *bucketMetadata.Owner.ID) {
  34. return bucketMetadata, s3err.ErrNone
  35. }
  36. if len(bucketMetadata.Acl) > 0 {
  37. reqGrants := s3acl.DetermineRequiredGrants(requestAccountId, s3_constants.PermissionWriteAcp)
  38. for _, bucketGrant := range bucketMetadata.Acl {
  39. for _, reqGrant := range reqGrants {
  40. if s3acl.GrantEquals(bucketGrant, reqGrant) {
  41. return bucketMetadata, s3err.ErrNone
  42. }
  43. }
  44. }
  45. }
  46. glog.V(3).Infof("acl denied! request account id: %s", requestAccountId)
  47. return nil, s3err.ErrAccessDenied
  48. }
  49. func updateBucketEntry(s3a *S3ApiServer, entry *filer_pb.Entry) error {
  50. return s3a.updateEntry(s3a.option.BucketsPath, entry)
  51. }
  52. // Check Bucket/BucketAcl Read related access
  53. // includes:
  54. // - HeadBucketHandler
  55. // - GetBucketAclHandler
  56. // - ListObjectsV1Handler
  57. // - ListObjectsV2Handler
  58. // - ListMultipartUploadsHandler
  59. func (s3a *S3ApiServer) checkAccessForReadBucket(r *http.Request, bucket, aclAction string) (*BucketMetaData, s3err.ErrorCode) {
  60. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  61. if errCode != s3err.ErrNone {
  62. return nil, errCode
  63. }
  64. if bucketMetadata.ObjectOwnership == s3_constants.OwnershipBucketOwnerEnforced {
  65. return bucketMetadata, s3err.ErrNone
  66. }
  67. requestAccountId := s3acl.GetAccountId(r)
  68. if s3acl.ValidateAccount(requestAccountId, *bucketMetadata.Owner.ID) {
  69. return bucketMetadata, s3err.ErrNone
  70. }
  71. if len(bucketMetadata.Acl) > 0 {
  72. reqGrants := s3acl.DetermineRequiredGrants(requestAccountId, aclAction)
  73. for _, bucketGrant := range bucketMetadata.Acl {
  74. for _, reqGrant := range reqGrants {
  75. if s3acl.GrantEquals(bucketGrant, reqGrant) {
  76. return bucketMetadata, s3err.ErrNone
  77. }
  78. }
  79. }
  80. }
  81. glog.V(3).Infof("acl denied! request account id: %s", requestAccountId)
  82. return nil, s3err.ErrAccessDenied
  83. }
  84. // Check ObjectAcl-Read related access
  85. // includes:
  86. // - GetObjectAclHandler
  87. func (s3a *S3ApiServer) checkAccessForReadObjectAcl(r *http.Request, bucket, object string) (acp *s3.AccessControlPolicy, errCode s3err.ErrorCode) {
  88. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  89. if errCode != s3err.ErrNone {
  90. return nil, errCode
  91. }
  92. getAcpFunc := func() (*s3.AccessControlPolicy, s3err.ErrorCode) {
  93. entry, err := getObjectEntry(s3a, bucket, object)
  94. if err != nil {
  95. if err == filer_pb.ErrNotFound {
  96. return nil, s3err.ErrNoSuchKey
  97. } else {
  98. return nil, s3err.ErrInternalError
  99. }
  100. }
  101. if entry.IsDirectory {
  102. return nil, s3err.ErrExistingObjectIsDirectory
  103. }
  104. acpOwnerId := s3acl.GetAcpOwner(entry.Extended, *bucketMetadata.Owner.ID)
  105. acpOwnerName := s3a.iam.GetAccountNameById(acpOwnerId)
  106. acpGrants := s3acl.GetAcpGrants(&acpOwnerId, entry.Extended)
  107. acp = &s3.AccessControlPolicy{
  108. Owner: &s3.Owner{
  109. ID: &acpOwnerId,
  110. DisplayName: &acpOwnerName,
  111. },
  112. Grants: acpGrants,
  113. }
  114. return acp, s3err.ErrNone
  115. }
  116. if bucketMetadata.ObjectOwnership == s3_constants.OwnershipBucketOwnerEnforced {
  117. return getAcpFunc()
  118. }
  119. requestAccountId := s3acl.GetAccountId(r)
  120. acp, errCode = getAcpFunc()
  121. if errCode != s3err.ErrNone {
  122. return nil, errCode
  123. }
  124. if s3acl.ValidateAccount(requestAccountId, *acp.Owner.ID) {
  125. return acp, s3err.ErrNone
  126. }
  127. if acp.Grants != nil {
  128. reqGrants := s3acl.DetermineRequiredGrants(requestAccountId, s3_constants.PermissionReadAcp)
  129. for _, requiredGrant := range reqGrants {
  130. for _, grant := range acp.Grants {
  131. if s3acl.GrantEquals(requiredGrant, grant) {
  132. return acp, s3err.ErrNone
  133. }
  134. }
  135. }
  136. }
  137. glog.V(3).Infof("CheckAccessForReadObjectAcl denied! request account id: %s", requestAccountId)
  138. return nil, s3err.ErrAccessDenied
  139. }
  140. // Check Object-Read related access
  141. // includes:
  142. // - GetObjectHandler
  143. //
  144. // offload object access validation to Filer layer
  145. // - CheckObjectAccessForReadObject
  146. func (s3a *S3ApiServer) checkBucketAccessForReadObject(r *http.Request, bucket string) s3err.ErrorCode {
  147. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  148. if errCode != s3err.ErrNone {
  149. return errCode
  150. }
  151. if bucketMetadata.ObjectOwnership != s3_constants.OwnershipBucketOwnerEnforced {
  152. //offload object acl validation to filer layer
  153. _, defaultErrorCode := s3a.checkAccessForReadBucket(r, bucket, s3_constants.PermissionRead)
  154. if defaultErrorCode != s3err.ErrNone {
  155. r.Header.Set(s3_constants.XAmzBucketAccessDenied, "true")
  156. }
  157. r.Header.Set(s3_constants.XAmzBucketOwnerId, *bucketMetadata.Owner.ID)
  158. }
  159. return s3err.ErrNone
  160. }
  161. // Check ObjectAcl-Write related access
  162. // includes:
  163. // - PutObjectAclHandler
  164. func (s3a *S3ApiServer) checkAccessForWriteObjectAcl(r *http.Request, bucket, object string) (*filer_pb.Entry, string, []*s3.Grant, s3err.ErrorCode) {
  165. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  166. if errCode != s3err.ErrNone {
  167. return nil, "", nil, errCode
  168. }
  169. requestAccountId := s3acl.GetAccountId(r)
  170. reqOwnerId, grants, errCode := s3acl.ExtractObjectAcl(r, s3a.iam, bucketMetadata.ObjectOwnership, *bucketMetadata.Owner.ID, requestAccountId, false)
  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. //object acl
  178. objectEntry, err := getObjectEntry(s3a, bucket, object)
  179. if err != nil {
  180. if err == filer_pb.ErrNotFound {
  181. return nil, "", nil, s3err.ErrNoSuchKey
  182. }
  183. return nil, "", nil, s3err.ErrInternalError
  184. }
  185. if objectEntry.IsDirectory {
  186. return nil, "", nil, s3err.ErrExistingObjectIsDirectory
  187. }
  188. objectOwner := s3acl.GetAcpOwner(objectEntry.Extended, *bucketMetadata.Owner.ID)
  189. //object owner is immutable
  190. if reqOwnerId != "" && reqOwnerId != objectOwner {
  191. return nil, "", nil, s3err.ErrAccessDenied
  192. }
  193. if s3acl.ValidateAccount(requestAccountId, objectOwner) {
  194. return objectEntry, objectOwner, grants, s3err.ErrNone
  195. }
  196. objectGrants := s3acl.GetAcpGrants(nil, objectEntry.Extended)
  197. if objectGrants != nil {
  198. requiredGrants := s3acl.DetermineRequiredGrants(requestAccountId, s3_constants.PermissionWriteAcp)
  199. for _, objectGrant := range objectGrants {
  200. for _, requiredGrant := range requiredGrants {
  201. if s3acl.GrantEquals(objectGrant, requiredGrant) {
  202. return objectEntry, objectOwner, grants, s3err.ErrNone
  203. }
  204. }
  205. }
  206. }
  207. glog.V(3).Infof("checkAccessForWriteObjectAcl denied! request account id: %s", requestAccountId)
  208. return nil, "", nil, s3err.ErrAccessDenied
  209. }
  210. func updateObjectEntry(s3a *S3ApiServer, bucket, object string, entry *filer_pb.Entry) error {
  211. dir, _ := filepath.Split(object)
  212. return s3a.updateEntry(util.Join(s3a.option.BucketsPath, bucket, dir), entry)
  213. }
  214. // CheckAccessForPutObject Check ACL for PutObject API
  215. // includes:
  216. // - PutObjectHandler
  217. func (s3a *S3ApiServer) CheckAccessForPutObject(r *http.Request, bucket, object string) s3err.ErrorCode {
  218. accountId := s3acl.GetAccountId(r)
  219. return s3a.checkAccessForPutObject(r, bucket, object, accountId)
  220. }
  221. // CheckAccessForPutObjectPartHandler Check Acl for Upload object part
  222. // includes:
  223. // - PutObjectPartHandler
  224. func (s3a *S3ApiServer) CheckAccessForPutObjectPartHandler(r *http.Request, bucket string) s3err.ErrorCode {
  225. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  226. if errCode != s3err.ErrNone {
  227. return errCode
  228. }
  229. if bucketMetadata.ObjectOwnership == s3_constants.OwnershipBucketOwnerEnforced {
  230. return s3err.ErrNone
  231. }
  232. accountId := s3acl.GetAccountId(r)
  233. if !CheckBucketAccess(accountId, bucketMetadata, s3_constants.PermissionWrite) {
  234. return s3err.ErrAccessDenied
  235. }
  236. return s3err.ErrNone
  237. }
  238. // CheckAccessForNewMultipartUpload Check Acl for API
  239. // includes:
  240. // - NewMultipartUploadHandler
  241. func (s3a *S3ApiServer) CheckAccessForNewMultipartUpload(r *http.Request, bucket, object string) (s3err.ErrorCode, string) {
  242. accountId := s3acl.GetAccountId(r)
  243. if accountId == AccountAnonymous.Id {
  244. return s3err.ErrAccessDenied, ""
  245. }
  246. errCode := s3a.checkAccessForPutObject(r, bucket, object, accountId)
  247. return errCode, accountId
  248. }
  249. func (s3a *S3ApiServer) CheckAccessForAbortMultipartUpload(r *http.Request, bucket, object string) s3err.ErrorCode {
  250. return s3a.CheckAccessWithBucketOwnerAndInitiator(r, bucket, object)
  251. }
  252. func (s3a *S3ApiServer) CheckAccessForCompleteMultipartUpload(r *http.Request, bucket, object string) s3err.ErrorCode {
  253. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  254. if errCode != s3err.ErrNone {
  255. return errCode
  256. }
  257. if bucketMetadata.ObjectOwnership != s3_constants.OwnershipBucketOwnerEnforced {
  258. accountId := s3acl.GetAccountId(r)
  259. if !CheckBucketAccess(accountId, bucketMetadata, s3_constants.PermissionWrite) {
  260. return s3err.ErrAccessDenied
  261. }
  262. }
  263. return s3err.ErrNone
  264. }
  265. func (s3a *S3ApiServer) CheckAccessForListMultipartUploadParts(r *http.Request, bucket, object string) s3err.ErrorCode {
  266. return s3a.CheckAccessWithBucketOwnerAndInitiator(r, bucket, object)
  267. }
  268. // CheckAccessWithBucketOwnerAndInitiator Check Access Permission with 'bucketOwner' and 'multipartUpload initiator'
  269. func (s3a *S3ApiServer) CheckAccessWithBucketOwnerAndInitiator(r *http.Request, bucket, object string) s3err.ErrorCode {
  270. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  271. if errCode != s3err.ErrNone {
  272. return errCode
  273. }
  274. //bucket access allowed
  275. accountId := s3acl.GetAccountId(r)
  276. if s3acl.ValidateAccount(*bucketMetadata.Owner.ID, accountId) {
  277. return s3err.ErrNone
  278. }
  279. //multipart initiator allowed
  280. entry, err := getMultipartUpload(s3a, bucket, object)
  281. if err != nil {
  282. if err != filer_pb.ErrNotFound {
  283. return s3err.ErrInternalError
  284. }
  285. } else {
  286. uploadInitiator, ok := entry.Extended[s3_constants.ExtAmzMultipartInitiator]
  287. if !ok || accountId == string(uploadInitiator) {
  288. return s3err.ErrNone
  289. }
  290. }
  291. glog.V(3).Infof("CheckAccessWithBucketOwnerAndInitiator denied! request account id: %s", accountId)
  292. return s3err.ErrAccessDenied
  293. }
  294. func (s3a *S3ApiServer) checkAccessForPutObject(r *http.Request, bucket, object, requestAccountId string) s3err.ErrorCode {
  295. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  296. if errCode != s3err.ErrNone {
  297. return errCode
  298. }
  299. // if ownership is 'OwnershipBucketOwnerEnforced', acl is not supportedG
  300. if bucketMetadata.ObjectOwnership == s3_constants.OwnershipBucketOwnerEnforced {
  301. _, _, errCode := s3acl.ExtractObjectAcl(r, s3a.iam, bucketMetadata.ObjectOwnership, *bucketMetadata.Owner.ID, requestAccountId, true)
  302. if errCode != s3err.ErrNone {
  303. return errCode
  304. }
  305. return s3err.ErrNone
  306. }
  307. requestOwnerId, grants, errCode := s3acl.ExtractObjectAcl(r, s3a.iam, bucketMetadata.ObjectOwnership, *bucketMetadata.Owner.ID, requestAccountId, true)
  308. if errCode != s3err.ErrNone {
  309. return errCode
  310. }
  311. if !CheckBucketAccess(requestAccountId, bucketMetadata, s3_constants.PermissionWrite) {
  312. return s3err.ErrAccessDenied
  313. }
  314. if requestOwnerId == "" {
  315. requestOwnerId = requestAccountId
  316. }
  317. entry, err := getObjectEntry(s3a, bucket, object)
  318. if err != nil {
  319. if err == filer_pb.ErrNotFound {
  320. s3acl.SetAcpOwnerHeader(r, requestOwnerId)
  321. s3acl.SetAcpGrantsHeader(r, grants)
  322. return s3err.ErrNone
  323. }
  324. return s3err.ErrInternalError
  325. }
  326. objectOwnerId := s3acl.GetAcpOwner(entry.Extended, *bucketMetadata.Owner.ID)
  327. //object owner is immutable
  328. if !s3acl.ValidateAccount(requestOwnerId, objectOwnerId, *bucketMetadata.Owner.ID) {
  329. return s3err.ErrAccessDenied
  330. }
  331. s3acl.SetAcpOwnerHeader(r, objectOwnerId)
  332. s3acl.SetAcpGrantsHeader(r, grants)
  333. return s3err.ErrNone
  334. }
  335. func CheckBucketAccess(requestAccountId string, bucketMetadata *BucketMetaData, permission string) bool {
  336. if s3acl.ValidateAccount(requestAccountId, *bucketMetadata.Owner.ID) {
  337. return true
  338. } else {
  339. if len(bucketMetadata.Acl) > 0 {
  340. reqGrants := s3acl.DetermineRequiredGrants(requestAccountId, permission)
  341. for _, bucketGrant := range bucketMetadata.Acl {
  342. for _, requiredGrant := range reqGrants {
  343. if s3acl.GrantEquals(bucketGrant, requiredGrant) {
  344. return true
  345. }
  346. }
  347. }
  348. }
  349. }
  350. glog.V(3).Infof("CheckBucketAccess denied! request account id: %s", requestAccountId)
  351. return false
  352. }
  353. func getObjectEntry(s3a *S3ApiServer, bucket, object string) (*filer_pb.Entry, error) {
  354. return s3a.getEntry(util.Join(s3a.option.BucketsPath, bucket), object)
  355. }
  356. func getMultipartUpload(s3a *S3ApiServer, bucket, object string) (*filer_pb.Entry, error) {
  357. return s3a.getEntry(s3a.genUploadsFolder(bucket), object)
  358. }