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.

419 lines
13 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. // CheckAccessForCompleteMultipartUpload Check Acl for CompleteMultipartUpload API
  247. // includes:
  248. // - CompleteMultipartUploadHandler
  249. func (s3a *S3ApiServer) CheckAccessForCompleteMultipartUpload(r *http.Request, bucket, object string) s3err.ErrorCode {
  250. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  251. if errCode != s3err.ErrNone {
  252. return errCode
  253. }
  254. //bucket access allowed
  255. accountId := s3acl.GetAccountId(r)
  256. if accountId == *bucketMetadata.Owner.ID {
  257. return s3err.ErrNone
  258. } else {
  259. if len(bucketMetadata.Acl) > 0 {
  260. reqGrants := s3acl.DetermineReqGrants(accountId, s3_constants.PermissionWrite)
  261. for _, bucketGrant := range bucketMetadata.Acl {
  262. for _, requiredGrant := range reqGrants {
  263. if s3acl.GrantEquals(bucketGrant, requiredGrant) {
  264. return s3err.ErrNone
  265. }
  266. }
  267. }
  268. }
  269. }
  270. glog.V(3).Infof("acl denied! request account id: %s", accountId)
  271. return s3err.ErrAccessDenied
  272. }
  273. func (s3a *S3ApiServer) checkAccessForWriteObject(r *http.Request, bucket, object, accountId string) s3err.ErrorCode {
  274. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  275. if errCode != s3err.ErrNone {
  276. return errCode
  277. }
  278. if bucketMetadata.ObjectOwnership == s3_constants.OwnershipBucketOwnerEnforced {
  279. // validate grants (only bucketOwnerFullControl acl is allowed)
  280. _, grants, errCode := s3acl.ParseAndValidateAclHeaders(r, s3a.accountManager, bucketMetadata.ObjectOwnership, *bucketMetadata.Owner.ID, accountId, false)
  281. if errCode != s3err.ErrNone {
  282. return errCode
  283. }
  284. if len(grants) > 1 {
  285. return s3err.AccessControlListNotSupported
  286. }
  287. bucketOwnerFullControlGrant := &s3.Grant{
  288. Permission: &s3_constants.PermissionFullControl,
  289. Grantee: &s3.Grantee{
  290. Type: &s3_constants.GrantTypeCanonicalUser,
  291. ID: bucketMetadata.Owner.ID,
  292. },
  293. }
  294. if len(grants) == 0 {
  295. return s3err.ErrNone
  296. }
  297. if s3acl.GrantEquals(bucketOwnerFullControlGrant, grants[0]) {
  298. return s3err.ErrNone
  299. }
  300. return s3err.AccessControlListNotSupported
  301. }
  302. //bucket access allowed
  303. bucketAclAllowed := false
  304. if accountId == *bucketMetadata.Owner.ID {
  305. bucketAclAllowed = true
  306. } else {
  307. if len(bucketMetadata.Acl) > 0 {
  308. reqGrants := s3acl.DetermineReqGrants(accountId, s3_constants.PermissionWrite)
  309. bucketLoop:
  310. for _, bucketGrant := range bucketMetadata.Acl {
  311. for _, requiredGrant := range reqGrants {
  312. if s3acl.GrantEquals(bucketGrant, requiredGrant) {
  313. bucketAclAllowed = true
  314. break bucketLoop
  315. }
  316. }
  317. }
  318. }
  319. }
  320. if !bucketAclAllowed {
  321. glog.V(3).Infof("acl denied! request account id: %s", accountId)
  322. return s3err.ErrAccessDenied
  323. }
  324. //object access allowed
  325. entry, err := getObjectEntry(s3a, bucket, object)
  326. if err != nil {
  327. if err != filer_pb.ErrNotFound {
  328. return s3err.ErrInternalError
  329. }
  330. } else {
  331. if entry.IsDirectory {
  332. return s3err.ErrExistingObjectIsDirectory
  333. }
  334. //Only the owner of the bucket and the owner of the object can overwrite the object
  335. objectOwner := s3acl.GetAcpOwner(entry.Extended, *bucketMetadata.Owner.ID)
  336. if accountId != objectOwner && accountId != *bucketMetadata.Owner.ID {
  337. glog.V(3).Infof("acl denied! request account id: %s, expect account id: %s", accountId, *bucketMetadata.Owner.ID)
  338. return s3err.ErrAccessDenied
  339. }
  340. }
  341. ownerId, grants, errCode := s3acl.ParseAndValidateAclHeadersOrElseDefault(r, s3a.accountManager, bucketMetadata.ObjectOwnership, *bucketMetadata.Owner.ID, accountId, false)
  342. if errCode != s3err.ErrNone {
  343. return errCode
  344. }
  345. s3acl.SetAcpOwnerHeader(r, ownerId)
  346. s3acl.SetAcpGrantsHeader(r, grants)
  347. return s3err.ErrNone
  348. }
  349. func getObjectEntry(s3a *S3ApiServer, bucket, object string) (*filer_pb.Entry, error) {
  350. return s3a.getEntry(util.Join(s3a.option.BucketsPath, bucket), object)
  351. }
  352. func (s3a *S3ApiServer) ExtractBucketAcp(r *http.Request) (owner string, grants []*s3.Grant, errCode s3err.ErrorCode) {
  353. accountId := s3acl.GetAccountId(r)
  354. ownership := s3_constants.DefaultOwnershipForCreate
  355. if ownership == s3_constants.OwnershipBucketOwnerEnforced {
  356. return accountId, []*s3.Grant{
  357. {
  358. Permission: &s3_constants.PermissionFullControl,
  359. Grantee: &s3.Grantee{
  360. Type: &s3_constants.GrantTypeCanonicalUser,
  361. ID: &accountId,
  362. },
  363. },
  364. }, s3err.ErrNone
  365. } else {
  366. return s3acl.ParseAndValidateAclHeadersOrElseDefault(r, s3a.accountManager, ownership, accountId, accountId, false)
  367. }
  368. }