api-bucket-policy.go (4006B)
1 /* 2 * MinIO Go Library for Amazon S3 Compatible Cloud Storage 3 * Copyright 2020 MinIO, Inc. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package minio 18 19 import ( 20 "context" 21 "io" 22 "net/http" 23 "net/url" 24 "strings" 25 26 "github.com/minio/minio-go/v7/pkg/s3utils" 27 ) 28 29 // SetBucketPolicy sets the access permissions on an existing bucket. 30 func (c *Client) SetBucketPolicy(ctx context.Context, bucketName, policy string) error { 31 // Input validation. 32 if err := s3utils.CheckValidBucketName(bucketName); err != nil { 33 return err 34 } 35 36 // If policy is empty then delete the bucket policy. 37 if policy == "" { 38 return c.removeBucketPolicy(ctx, bucketName) 39 } 40 41 // Save the updated policies. 42 return c.putBucketPolicy(ctx, bucketName, policy) 43 } 44 45 // Saves a new bucket policy. 46 func (c *Client) putBucketPolicy(ctx context.Context, bucketName, policy string) error { 47 // Get resources properly escaped and lined up before 48 // using them in http request. 49 urlValues := make(url.Values) 50 urlValues.Set("policy", "") 51 52 reqMetadata := requestMetadata{ 53 bucketName: bucketName, 54 queryValues: urlValues, 55 contentBody: strings.NewReader(policy), 56 contentLength: int64(len(policy)), 57 } 58 59 // Execute PUT to upload a new bucket policy. 60 resp, err := c.executeMethod(ctx, http.MethodPut, reqMetadata) 61 defer closeResponse(resp) 62 if err != nil { 63 return err 64 } 65 if resp != nil { 66 if resp.StatusCode != http.StatusNoContent && resp.StatusCode != http.StatusOK { 67 return httpRespToErrorResponse(resp, bucketName, "") 68 } 69 } 70 return nil 71 } 72 73 // Removes all policies on a bucket. 74 func (c *Client) removeBucketPolicy(ctx context.Context, bucketName string) error { 75 // Get resources properly escaped and lined up before 76 // using them in http request. 77 urlValues := make(url.Values) 78 urlValues.Set("policy", "") 79 80 // Execute DELETE on objectName. 81 resp, err := c.executeMethod(ctx, http.MethodDelete, requestMetadata{ 82 bucketName: bucketName, 83 queryValues: urlValues, 84 contentSHA256Hex: emptySHA256Hex, 85 }) 86 defer closeResponse(resp) 87 if err != nil { 88 return err 89 } 90 91 if resp.StatusCode != http.StatusNoContent { 92 return httpRespToErrorResponse(resp, bucketName, "") 93 } 94 95 return nil 96 } 97 98 // GetBucketPolicy returns the current policy 99 func (c *Client) GetBucketPolicy(ctx context.Context, bucketName string) (string, error) { 100 // Input validation. 101 if err := s3utils.CheckValidBucketName(bucketName); err != nil { 102 return "", err 103 } 104 bucketPolicy, err := c.getBucketPolicy(ctx, bucketName) 105 if err != nil { 106 errResponse := ToErrorResponse(err) 107 if errResponse.Code == "NoSuchBucketPolicy" { 108 return "", nil 109 } 110 return "", err 111 } 112 return bucketPolicy, nil 113 } 114 115 // Request server for current bucket policy. 116 func (c *Client) getBucketPolicy(ctx context.Context, bucketName string) (string, error) { 117 // Get resources properly escaped and lined up before 118 // using them in http request. 119 urlValues := make(url.Values) 120 urlValues.Set("policy", "") 121 122 // Execute GET on bucket to list objects. 123 resp, err := c.executeMethod(ctx, http.MethodGet, requestMetadata{ 124 bucketName: bucketName, 125 queryValues: urlValues, 126 contentSHA256Hex: emptySHA256Hex, 127 }) 128 129 defer closeResponse(resp) 130 if err != nil { 131 return "", err 132 } 133 134 if resp != nil { 135 if resp.StatusCode != http.StatusOK { 136 return "", httpRespToErrorResponse(resp, bucketName, "") 137 } 138 } 139 140 bucketPolicyBuf, err := io.ReadAll(resp.Body) 141 if err != nil { 142 return "", err 143 } 144 145 policy := string(bucketPolicyBuf) 146 return policy, err 147 }