mirror of
				https://github.com/minio/minio.git
				synced 2025-10-26 22:01:30 +01:00 
			
		
		
		
	This feature also changes the default port where the browser is running, now the port has moved to 9001 and it can be configured with ``` --console-address ":9001" ```
		
			
				
	
	
		
			289 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			289 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright (c) 2015-2021 MinIO, Inc.
 | |
| //
 | |
| // This file is part of MinIO Object Storage stack
 | |
| //
 | |
| // This program is free software: you can redistribute it and/or modify
 | |
| // it under the terms of the GNU Affero General Public License as published by
 | |
| // the Free Software Foundation, either version 3 of the License, or
 | |
| // (at your option) any later version.
 | |
| //
 | |
| // This program is distributed in the hope that it will be useful
 | |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
| // GNU Affero General Public License for more details.
 | |
| //
 | |
| // You should have received a copy of the GNU Affero General Public License
 | |
| // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | |
| 
 | |
| package cmd
 | |
| 
 | |
| import (
 | |
| 	"encoding/xml"
 | |
| 	"io"
 | |
| 	"net/http"
 | |
| 
 | |
| 	"github.com/gorilla/mux"
 | |
| 	xhttp "github.com/minio/minio/internal/http"
 | |
| 	"github.com/minio/minio/internal/logger"
 | |
| 	"github.com/minio/pkg/bucket/policy"
 | |
| )
 | |
| 
 | |
| // Data types used for returning dummy access control
 | |
| // policy XML, these variables shouldn't be used elsewhere
 | |
| // they are only defined to be used in this file alone.
 | |
| type grantee struct {
 | |
| 	XMLNS       string `xml:"xmlns:xsi,attr"`
 | |
| 	XMLXSI      string `xml:"xsi:type,attr"`
 | |
| 	Type        string `xml:"Type"`
 | |
| 	ID          string `xml:"ID,omitempty"`
 | |
| 	DisplayName string `xml:"DisplayName,omitempty"`
 | |
| 	URI         string `xml:"URI,omitempty"`
 | |
| }
 | |
| 
 | |
| type grant struct {
 | |
| 	Grantee    grantee `xml:"Grantee"`
 | |
| 	Permission string  `xml:"Permission"`
 | |
| }
 | |
| 
 | |
| type accessControlPolicy struct {
 | |
| 	XMLName           xml.Name `xml:"AccessControlPolicy"`
 | |
| 	Owner             Owner    `xml:"Owner"`
 | |
| 	AccessControlList struct {
 | |
| 		Grants []grant `xml:"Grant"`
 | |
| 	} `xml:"AccessControlList"`
 | |
| }
 | |
| 
 | |
| // PutBucketACLHandler - PUT Bucket ACL
 | |
| // -----------------
 | |
| // This operation uses the ACL subresource
 | |
| // to set ACL for a bucket, this is a dummy call
 | |
| // only responds success if the ACL is private.
 | |
| func (api objectAPIHandlers) PutBucketACLHandler(w http.ResponseWriter, r *http.Request) {
 | |
| 	ctx := newContext(r, w, "PutBucketACL")
 | |
| 
 | |
| 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r))
 | |
| 
 | |
| 	vars := mux.Vars(r)
 | |
| 	bucket := vars["bucket"]
 | |
| 
 | |
| 	objAPI := api.ObjectAPI()
 | |
| 	if objAPI == nil {
 | |
| 		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	// Allow putBucketACL if policy action is set, since this is a dummy call
 | |
| 	// we are simply re-purposing the bucketPolicyAction.
 | |
| 	if s3Error := checkRequestAuthType(ctx, r, policy.PutBucketPolicyAction, bucket, ""); s3Error != ErrNone {
 | |
| 		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	// Before proceeding validate if bucket exists.
 | |
| 	_, err := objAPI.GetBucketInfo(ctx, bucket)
 | |
| 	if err != nil {
 | |
| 		writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	aclHeader := r.Header.Get(xhttp.AmzACL)
 | |
| 	if aclHeader == "" {
 | |
| 		acl := &accessControlPolicy{}
 | |
| 		if err = xmlDecoder(r.Body, acl, r.ContentLength); err != nil {
 | |
| 			if err == io.EOF {
 | |
| 				writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrMissingSecurityHeader),
 | |
| 					r.URL)
 | |
| 				return
 | |
| 			}
 | |
| 			writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		if len(acl.AccessControlList.Grants) == 0 {
 | |
| 			writeErrorResponse(ctx, w, toAPIError(ctx, NotImplemented{}), r.URL)
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		if acl.AccessControlList.Grants[0].Permission != "FULL_CONTROL" {
 | |
| 			writeErrorResponse(ctx, w, toAPIError(ctx, NotImplemented{}), r.URL)
 | |
| 			return
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if aclHeader != "" && aclHeader != "private" {
 | |
| 		writeErrorResponse(ctx, w, toAPIError(ctx, NotImplemented{}), r.URL)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	w.(http.Flusher).Flush()
 | |
| }
 | |
| 
 | |
| // GetBucketACLHandler - GET Bucket ACL
 | |
| // -----------------
 | |
| // This operation uses the ACL
 | |
| // subresource to return the ACL of a specified bucket.
 | |
| func (api objectAPIHandlers) GetBucketACLHandler(w http.ResponseWriter, r *http.Request) {
 | |
| 	ctx := newContext(r, w, "GetBucketACL")
 | |
| 
 | |
| 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r))
 | |
| 
 | |
| 	vars := mux.Vars(r)
 | |
| 	bucket := vars["bucket"]
 | |
| 
 | |
| 	objAPI := api.ObjectAPI()
 | |
| 	if objAPI == nil {
 | |
| 		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	// Allow getBucketACL if policy action is set, since this is a dummy call
 | |
| 	// we are simply re-purposing the bucketPolicyAction.
 | |
| 	if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketPolicyAction, bucket, ""); s3Error != ErrNone {
 | |
| 		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	// Before proceeding validate if bucket exists.
 | |
| 	_, err := objAPI.GetBucketInfo(ctx, bucket)
 | |
| 	if err != nil {
 | |
| 		writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	acl := &accessControlPolicy{}
 | |
| 	acl.AccessControlList.Grants = append(acl.AccessControlList.Grants, grant{
 | |
| 		Grantee: grantee{
 | |
| 			XMLNS:  "http://www.w3.org/2001/XMLSchema-instance",
 | |
| 			XMLXSI: "CanonicalUser",
 | |
| 			Type:   "CanonicalUser",
 | |
| 		},
 | |
| 		Permission: "FULL_CONTROL",
 | |
| 	})
 | |
| 
 | |
| 	if err := xml.NewEncoder(w).Encode(acl); err != nil {
 | |
| 		writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	w.(http.Flusher).Flush()
 | |
| }
 | |
| 
 | |
| // PutObjectACLHandler - PUT Object ACL
 | |
| // -----------------
 | |
| // This operation uses the ACL subresource
 | |
| // to set ACL for a bucket, this is a dummy call
 | |
| // only responds success if the ACL is private.
 | |
| func (api objectAPIHandlers) PutObjectACLHandler(w http.ResponseWriter, r *http.Request) {
 | |
| 	ctx := newContext(r, w, "PutObjectACL")
 | |
| 
 | |
| 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r))
 | |
| 
 | |
| 	vars := mux.Vars(r)
 | |
| 	bucket := vars["bucket"]
 | |
| 	object, err := unescapePath(vars["object"])
 | |
| 	if err != nil {
 | |
| 		writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	objAPI := api.ObjectAPI()
 | |
| 	if objAPI == nil {
 | |
| 		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	// Allow putObjectACL if policy action is set, since this is a dummy call
 | |
| 	// we are simply re-purposing the bucketPolicyAction.
 | |
| 	if s3Error := checkRequestAuthType(ctx, r, policy.PutBucketPolicyAction, bucket, ""); s3Error != ErrNone {
 | |
| 		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	// Before proceeding validate if object exists.
 | |
| 	_, err = objAPI.GetObjectInfo(ctx, bucket, object, ObjectOptions{})
 | |
| 	if err != nil {
 | |
| 		writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	aclHeader := r.Header.Get(xhttp.AmzACL)
 | |
| 	if aclHeader == "" {
 | |
| 		acl := &accessControlPolicy{}
 | |
| 		if err = xmlDecoder(r.Body, acl, r.ContentLength); err != nil {
 | |
| 			writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		if len(acl.AccessControlList.Grants) == 0 {
 | |
| 			writeErrorResponse(ctx, w, toAPIError(ctx, NotImplemented{}), r.URL)
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		if acl.AccessControlList.Grants[0].Permission != "FULL_CONTROL" {
 | |
| 			writeErrorResponse(ctx, w, toAPIError(ctx, NotImplemented{}), r.URL)
 | |
| 			return
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if aclHeader != "" && aclHeader != "private" {
 | |
| 		writeErrorResponse(ctx, w, toAPIError(ctx, NotImplemented{}), r.URL)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	w.(http.Flusher).Flush()
 | |
| }
 | |
| 
 | |
| // GetObjectACLHandler - GET Object ACL
 | |
| // -----------------
 | |
| // This operation uses the ACL
 | |
| // subresource to return the ACL of a specified object.
 | |
| func (api objectAPIHandlers) GetObjectACLHandler(w http.ResponseWriter, r *http.Request) {
 | |
| 	ctx := newContext(r, w, "GetObjectACL")
 | |
| 
 | |
| 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r))
 | |
| 
 | |
| 	vars := mux.Vars(r)
 | |
| 	bucket := vars["bucket"]
 | |
| 	object, err := unescapePath(vars["object"])
 | |
| 	if err != nil {
 | |
| 		writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	objAPI := api.ObjectAPI()
 | |
| 	if objAPI == nil {
 | |
| 		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	// Allow getObjectACL if policy action is set, since this is a dummy call
 | |
| 	// we are simply re-purposing the bucketPolicyAction.
 | |
| 	if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketPolicyAction, bucket, ""); s3Error != ErrNone {
 | |
| 		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	// Before proceeding validate if object exists.
 | |
| 	_, err = objAPI.GetObjectInfo(ctx, bucket, object, ObjectOptions{})
 | |
| 	if err != nil {
 | |
| 		writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	acl := &accessControlPolicy{}
 | |
| 	acl.AccessControlList.Grants = append(acl.AccessControlList.Grants, grant{
 | |
| 		Grantee: grantee{
 | |
| 			XMLNS:  "http://www.w3.org/2001/XMLSchema-instance",
 | |
| 			XMLXSI: "CanonicalUser",
 | |
| 			Type:   "CanonicalUser",
 | |
| 		},
 | |
| 		Permission: "FULL_CONTROL",
 | |
| 	})
 | |
| 	if err := xml.NewEncoder(w).Encode(acl); err != nil {
 | |
| 		writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	w.(http.Flusher).Flush()
 | |
| }
 |