api-get-object-acl.go (4338B)
1 /* 2 * MinIO Go Library for Amazon S3 Compatible Cloud Storage 3 * Copyright 2018 MinIO, Inc. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package minio 19 20 import ( 21 "context" 22 "encoding/xml" 23 "net/http" 24 "net/url" 25 ) 26 27 // Grantee represents the person being granted permissions. 28 type Grantee struct { 29 XMLName xml.Name `xml:"Grantee"` 30 ID string `xml:"ID"` 31 DisplayName string `xml:"DisplayName"` 32 URI string `xml:"URI"` 33 } 34 35 // Grant holds grant information 36 type Grant struct { 37 XMLName xml.Name `xml:"Grant"` 38 Grantee Grantee 39 Permission string `xml:"Permission"` 40 } 41 42 // AccessControlList contains the set of grantees and the permissions assigned to each grantee. 43 type AccessControlList struct { 44 XMLName xml.Name `xml:"AccessControlList"` 45 Grant []Grant 46 Permission string `xml:"Permission"` 47 } 48 49 type accessControlPolicy struct { 50 XMLName xml.Name `xml:"AccessControlPolicy"` 51 Owner Owner 52 AccessControlList AccessControlList 53 } 54 55 // GetObjectACL get object ACLs 56 func (c *Client) GetObjectACL(ctx context.Context, bucketName, objectName string) (*ObjectInfo, error) { 57 resp, err := c.executeMethod(ctx, http.MethodGet, requestMetadata{ 58 bucketName: bucketName, 59 objectName: objectName, 60 queryValues: url.Values{ 61 "acl": []string{""}, 62 }, 63 }) 64 if err != nil { 65 return nil, err 66 } 67 defer closeResponse(resp) 68 69 if resp.StatusCode != http.StatusOK { 70 return nil, httpRespToErrorResponse(resp, bucketName, objectName) 71 } 72 73 res := &accessControlPolicy{} 74 75 if err := xmlDecoder(resp.Body, res); err != nil { 76 return nil, err 77 } 78 79 objInfo, err := c.StatObject(ctx, bucketName, objectName, StatObjectOptions{}) 80 if err != nil { 81 return nil, err 82 } 83 84 objInfo.Owner.DisplayName = res.Owner.DisplayName 85 objInfo.Owner.ID = res.Owner.ID 86 87 objInfo.Grant = append(objInfo.Grant, res.AccessControlList.Grant...) 88 89 cannedACL := getCannedACL(res) 90 if cannedACL != "" { 91 objInfo.Metadata.Add("X-Amz-Acl", cannedACL) 92 return &objInfo, nil 93 } 94 95 grantACL := getAmzGrantACL(res) 96 for k, v := range grantACL { 97 objInfo.Metadata[k] = v 98 } 99 100 return &objInfo, nil 101 } 102 103 func getCannedACL(aCPolicy *accessControlPolicy) string { 104 grants := aCPolicy.AccessControlList.Grant 105 106 switch { 107 case len(grants) == 1: 108 if grants[0].Grantee.URI == "" && grants[0].Permission == "FULL_CONTROL" { 109 return "private" 110 } 111 case len(grants) == 2: 112 for _, g := range grants { 113 if g.Grantee.URI == "http://acs.amazonaws.com/groups/global/AuthenticatedUsers" && g.Permission == "READ" { 114 return "authenticated-read" 115 } 116 if g.Grantee.URI == "http://acs.amazonaws.com/groups/global/AllUsers" && g.Permission == "READ" { 117 return "public-read" 118 } 119 if g.Permission == "READ" && g.Grantee.ID == aCPolicy.Owner.ID { 120 return "bucket-owner-read" 121 } 122 } 123 case len(grants) == 3: 124 for _, g := range grants { 125 if g.Grantee.URI == "http://acs.amazonaws.com/groups/global/AllUsers" && g.Permission == "WRITE" { 126 return "public-read-write" 127 } 128 } 129 } 130 return "" 131 } 132 133 func getAmzGrantACL(aCPolicy *accessControlPolicy) map[string][]string { 134 grants := aCPolicy.AccessControlList.Grant 135 res := map[string][]string{} 136 137 for _, g := range grants { 138 switch { 139 case g.Permission == "READ": 140 res["X-Amz-Grant-Read"] = append(res["X-Amz-Grant-Read"], "id="+g.Grantee.ID) 141 case g.Permission == "WRITE": 142 res["X-Amz-Grant-Write"] = append(res["X-Amz-Grant-Write"], "id="+g.Grantee.ID) 143 case g.Permission == "READ_ACP": 144 res["X-Amz-Grant-Read-Acp"] = append(res["X-Amz-Grant-Read-Acp"], "id="+g.Grantee.ID) 145 case g.Permission == "WRITE_ACP": 146 res["X-Amz-Grant-Write-Acp"] = append(res["X-Amz-Grant-Write-Acp"], "id="+g.Grantee.ID) 147 case g.Permission == "FULL_CONTROL": 148 res["X-Amz-Grant-Full-Control"] = append(res["X-Amz-Grant-Full-Control"], "id="+g.Grantee.ID) 149 } 150 } 151 return res 152 }