[feat]: implement GetBucketPolicyStatus API (#11673)

additionally also add more APIs in notImplemented
list, adjust routing rules appropriately
This commit is contained in:
Harshavardhana 2021-03-01 23:10:33 -08:00 committed by GitHub
parent e8d8dfa3ae
commit b1bb3f7016
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 100 additions and 18 deletions

View File

@ -48,6 +48,12 @@ type LocationResponse struct {
Location string `xml:",chardata"`
}
// PolicyStatus captures information returned by GetBucketPolicyStatusHandler
type PolicyStatus struct {
XMLName xml.Name `xml:"http://s3.amazonaws.com/doc/2006-03-01/ PolicyStatus" json:"-"`
IsPublic string
}
// ListVersionsResponse - format for list bucket versions response.
type ListVersionsResponse struct {
XMLName xml.Name `xml:"http://s3.amazonaws.com/doc/2006-03-01/ ListVersionsResult" json:"-"`

View File

@ -185,6 +185,10 @@ func registerAPIRouter(router *mux.Router) {
bucket.Methods(http.MethodDelete).Path("/{object:.+}").HandlerFunc(
collectAPIStats("deleteobject", maxClients(httpTraceAll(api.DeleteObjectHandler))))
// PostRestoreObject
bucket.Methods(http.MethodPost).Path("/{object:.+}").HandlerFunc(
collectAPIStats("restoreobject", maxClients(httpTraceAll(api.PostRestoreObjectHandler)))).Queries("restore", "")
/// Bucket operations
// GetBucketLocation
bucket.Methods(http.MethodGet).HandlerFunc(
@ -262,9 +266,9 @@ func registerAPIRouter(router *mux.Router) {
// ListObjectVersions
bucket.Methods(http.MethodGet).HandlerFunc(
collectAPIStats("listobjectversions", maxClients(httpTraceAll(api.ListObjectVersionsHandler)))).Queries("versions", "")
// ListObjectsV1 (Legacy)
// GetBucketPolicyStatus
bucket.Methods(http.MethodGet).HandlerFunc(
collectAPIStats("listobjectsv1", maxClients(httpTraceAll(api.ListObjectsV1Handler))))
collectAPIStats("getpolicystatus", maxClients(httpTraceAll(api.GetBucketPolicyStatusHandler)))).Queries("policyStatus", "")
// PutBucketLifecycle
bucket.Methods(http.MethodPut).HandlerFunc(
collectAPIStats("putbucketlifecycle", maxClients(httpTraceAll(api.PutBucketLifecycleHandler)))).Queries("lifecycle", "")
@ -320,9 +324,9 @@ func registerAPIRouter(router *mux.Router) {
// DeleteBucket
bucket.Methods(http.MethodDelete).HandlerFunc(
collectAPIStats("deletebucket", maxClients(httpTraceAll(api.DeleteBucketHandler))))
// PostRestoreObject
bucket.Methods(http.MethodPost).Path("/{object:.+}").HandlerFunc(
collectAPIStats("restoreobject", maxClients(httpTraceAll(api.PostRestoreObjectHandler)))).Queries("restore", "")
// ListObjectsV1 (Legacy)
bucket.Methods(http.MethodGet).HandlerFunc(
collectAPIStats("listobjectsv1", maxClients(httpTraceAll(api.ListObjectsV1Handler))))
}
/// Root operation

View File

@ -1030,6 +1030,64 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
}
}
// GetBucketPolicyStatusHandler - Retrieves the policy status
// for an MinIO bucket, indicating whether the bucket is public.
func (api objectAPIHandlers) GetBucketPolicyStatusHandler(w http.ResponseWriter, r *http.Request) {
ctx := newContext(r, w, "GetBucketPolicyStatus")
defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r))
vars := mux.Vars(r)
bucket := vars["bucket"]
objectAPI := api.ObjectAPI()
if objectAPI == nil {
writeErrorResponseHeadersOnly(w, errorCodes.ToAPIErr(ErrServerNotInitialized))
return
}
if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketPolicyStatusAction, bucket, ""); s3Error != ErrNone {
writeErrorResponseHeadersOnly(w, errorCodes.ToAPIErr(s3Error))
return
}
// Check if bucket exists.
if _, err := objectAPI.GetBucketInfo(ctx, bucket); err != nil {
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return
}
// Check if anonymous (non-owner) has access to list objects.
readable := globalPolicySys.IsAllowed(policy.Args{
Action: policy.ListBucketAction,
BucketName: bucket,
ConditionValues: getConditionValues(r, "", "", nil),
IsOwner: false,
})
// Check if anonymous (non-owner) has access to upload objects.
writable := globalPolicySys.IsAllowed(policy.Args{
Action: policy.PutObjectAction,
BucketName: bucket,
ConditionValues: getConditionValues(r, "", "", nil),
IsOwner: false,
})
encodedSuccessResponse := encodeResponse(PolicyStatus{
IsPublic: func() string {
// Silly to have special 'boolean' values yes
// but complying with silly implementation
// https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketPolicyStatus.html
if readable && writable {
return "TRUE"
}
return "FALSE"
}(),
})
writeSuccessResponseXML(w, encodedSuccessResponse)
}
// HeadBucketHandler - HEAD Bucket
// ----------
// This operation is useful to determine if a bucket exists.

View File

@ -376,6 +376,10 @@ var notImplementedBucketResourceNames = map[string]struct{}{
"inventory": {},
"accelerate": {},
"requestPayment": {},
"analytics": {},
"intelligent-tiering": {},
"ownershipControls": {},
"publicAccessBlock": {},
}
// Checks requests for not implemented Bucket resources

View File

@ -471,10 +471,10 @@ func methodNotAllowedHandler(api string) func(w http.ResponseWriter, r *http.Req
HTTPStatusCode: http.StatusUpgradeRequired,
}, r.URL)
default:
desc := fmt.Sprintf("Unknown API request at %s", r.URL.Path)
writeErrorResponse(r.Context(), w, APIError{
Code: "XMinioUnknownAPIRequest",
Description: desc,
Code: "BadRequest",
Description: fmt.Sprintf("An error occurred when parsing the HTTP request %s at '%s'",
r.Method, r.URL.Path),
HTTPStatusCode: http.StatusBadRequest,
}, r.URL, guessIsBrowserReq(r))
}
@ -524,10 +524,10 @@ func errorResponseHandler(w http.ResponseWriter, r *http.Request) {
HTTPStatusCode: http.StatusUpgradeRequired,
}, r.URL)
default:
desc := fmt.Sprintf("Unknown API request at %s", r.URL.Path)
writeErrorResponse(r.Context(), w, APIError{
Code: "XMinioUnknownAPIRequest",
Description: desc,
Code: "BadRequest",
Description: fmt.Sprintf("An error occurred when parsing the HTTP request %s at '%s'",
r.Method, r.URL.Path),
HTTPStatusCode: http.StatusBadRequest,
}, r.URL, guessIsBrowserReq(r))
}

View File

@ -68,6 +68,9 @@ const (
// ListBucketAction - ListBucket Rest API action.
ListBucketAction = "s3:ListBucket"
// GetBucketPolicyStatusAction - Retrieves the policy status for a bucket.
GetBucketPolicyStatusAction = "s3:GetBucketPolicyStatus"
// ListBucketMultipartUploadsAction - ListMultipartUploads Rest API action.
ListBucketMultipartUploadsAction = "s3:ListBucketMultipartUploads"
@ -222,6 +225,7 @@ var supportedActions = map[Action]struct{}{
HeadBucketAction: {},
ListAllMyBucketsAction: {},
ListBucketAction: {},
GetBucketPolicyStatusAction: {},
ListBucketVersionsAction: {},
ListBucketMultipartUploadsAction: {},
ListenNotificationAction: {},
@ -315,6 +319,8 @@ var actionConditionKeyMap = map[Action]condition.KeySet{
GetBucketLocationAction: condition.NewKeySet(condition.CommonKeys...),
GetBucketPolicyStatusAction: condition.NewKeySet(condition.CommonKeys...),
GetObjectAction: condition.NewKeySet(
append([]condition.Key{
condition.S3XAmzServerSideEncryption,

View File

@ -67,6 +67,9 @@ const (
// ListBucketAction - ListBucket Rest API action.
ListBucketAction = "s3:ListBucket"
// GetBucketPolicyStatusAction - Retrieves the policy status for a bucket.
GetBucketPolicyStatusAction = "s3:GetBucketPolicyStatus"
// ListBucketVersionsAction - ListBucketVersions Rest API action.
ListBucketVersionsAction = "s3:ListBucketVersions"
@ -197,6 +200,7 @@ var supportedActions = map[Action]struct{}{
HeadBucketAction: {},
ListAllMyBucketsAction: {},
ListBucketAction: {},
GetBucketPolicyStatusAction: {},
ListBucketVersionsAction: {},
ListBucketMultipartUploadsAction: {},
ListenNotificationAction: {},