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.

381 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. // Check Object-Write related access
  230. // includes:
  231. // - PutObjectHandler
  232. // - PutObjectPartHandler
  233. func (s3a *S3ApiServer) checkAccessForWriteObject(r *http.Request, bucket, object string) s3err.ErrorCode {
  234. bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket)
  235. if errCode != s3err.ErrNone {
  236. return errCode
  237. }
  238. accountId := s3acl.GetAccountId(r)
  239. if bucketMetadata.ObjectOwnership == s3_constants.OwnershipBucketOwnerEnforced {
  240. // validate grants (only bucketOwnerFullControl acl is allowed)
  241. _, grants, errCode := s3acl.ParseAndValidateAclHeaders(r, s3a.accountManager, bucketMetadata.ObjectOwnership, *bucketMetadata.Owner.ID, accountId, false)
  242. if errCode != s3err.ErrNone {
  243. return errCode
  244. }
  245. if len(grants) > 1 {
  246. return s3err.AccessControlListNotSupported
  247. }
  248. bucketOwnerFullControlGrant := &s3.Grant{
  249. Permission: &s3_constants.PermissionFullControl,
  250. Grantee: &s3.Grantee{
  251. Type: &s3_constants.GrantTypeCanonicalUser,
  252. ID: bucketMetadata.Owner.ID,
  253. },
  254. }
  255. if len(grants) == 0 {
  256. // set default grants
  257. s3acl.SetAcpOwnerHeader(r, accountId)
  258. s3acl.SetAcpGrantsHeader(r, []*s3.Grant{bucketOwnerFullControlGrant})
  259. return s3err.ErrNone
  260. }
  261. if !s3acl.GrantEquals(bucketOwnerFullControlGrant, grants[0]) {
  262. return s3err.AccessControlListNotSupported
  263. }
  264. s3acl.SetAcpOwnerHeader(r, accountId)
  265. s3acl.SetAcpGrantsHeader(r, []*s3.Grant{bucketOwnerFullControlGrant})
  266. return s3err.ErrNone
  267. }
  268. //bucket access allowed
  269. bucketAclAllowed := false
  270. if accountId == *bucketMetadata.Owner.ID {
  271. bucketAclAllowed = true
  272. } else {
  273. if len(bucketMetadata.Acl) > 0 {
  274. reqGrants := s3acl.DetermineReqGrants(accountId, s3_constants.PermissionWrite)
  275. bucketLoop:
  276. for _, bucketGrant := range bucketMetadata.Acl {
  277. for _, requiredGrant := range reqGrants {
  278. if s3acl.GrantEquals(bucketGrant, requiredGrant) {
  279. bucketAclAllowed = true
  280. break bucketLoop
  281. }
  282. }
  283. }
  284. }
  285. }
  286. if !bucketAclAllowed {
  287. glog.V(3).Infof("acl denied! request account id: %s", accountId)
  288. return s3err.ErrAccessDenied
  289. }
  290. //object access allowed
  291. entry, err := getObjectEntry(s3a, bucket, object)
  292. if err != nil {
  293. if err != filer_pb.ErrNotFound {
  294. return s3err.ErrInternalError
  295. }
  296. } else {
  297. if entry.IsDirectory {
  298. return s3err.ErrExistingObjectIsDirectory
  299. }
  300. //Only the owner of the bucket and the owner of the object can overwrite the object
  301. objectOwner := s3acl.GetAcpOwner(entry.Extended, *bucketMetadata.Owner.ID)
  302. if accountId != objectOwner && accountId != *bucketMetadata.Owner.ID {
  303. glog.V(3).Infof("acl denied! request account id: %s, expect account id: %s", accountId, *bucketMetadata.Owner.ID)
  304. return s3err.ErrAccessDenied
  305. }
  306. }
  307. ownerId, grants, errCode := s3acl.ParseAndValidateAclHeadersOrElseDefault(r, s3a.accountManager, bucketMetadata.ObjectOwnership, *bucketMetadata.Owner.ID, accountId, false)
  308. if errCode != s3err.ErrNone {
  309. return errCode
  310. }
  311. s3acl.SetAcpOwnerHeader(r, ownerId)
  312. s3acl.SetAcpGrantsHeader(r, grants)
  313. return s3err.ErrNone
  314. }
  315. func getObjectEntry(s3a *S3ApiServer, bucket, object string) (*filer_pb.Entry, error) {
  316. return s3a.getEntry(util.Join(s3a.option.BucketsPath, bucket), object)
  317. }
  318. func (s3a *S3ApiServer) ExtractBucketAcp(r *http.Request) (owner string, grants []*s3.Grant, errCode s3err.ErrorCode) {
  319. accountId := s3acl.GetAccountId(r)
  320. ownership := s3_constants.DefaultOwnershipForCreate
  321. if ownership == s3_constants.OwnershipBucketOwnerEnforced {
  322. return accountId, []*s3.Grant{
  323. {
  324. Permission: &s3_constants.PermissionFullControl,
  325. Grantee: &s3.Grantee{
  326. Type: &s3_constants.GrantTypeCanonicalUser,
  327. ID: &accountId,
  328. },
  329. },
  330. }, s3err.ErrNone
  331. } else {
  332. return s3acl.ParseAndValidateAclHeadersOrElseDefault(r, s3a.accountManager, ownership, accountId, accountId, false)
  333. }
  334. }