parent
ed67a1269d
commit
b121c8588f
@ -1,121 +0,0 @@ |
|||||||
/* |
|
||||||
* Minimalist Object Storage, (C) 2015 Minio, Inc. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package api |
|
||||||
|
|
||||||
import ( |
|
||||||
"encoding/json" |
|
||||||
"net/http" |
|
||||||
|
|
||||||
"github.com/gorilla/mux" |
|
||||||
"github.com/minio-io/minio/pkg/iodine" |
|
||||||
"github.com/minio-io/minio/pkg/storage/drivers" |
|
||||||
"github.com/minio-io/minio/pkg/utils/log" |
|
||||||
) |
|
||||||
|
|
||||||
// PUT Bucket policy
|
|
||||||
// -----------------
|
|
||||||
// This implementation of the PUT operation uses the policy subresource
|
|
||||||
// to add to or replace a policy on a bucket
|
|
||||||
func (server *minioAPI) putBucketPolicyHandler(w http.ResponseWriter, req *http.Request) { |
|
||||||
vars := mux.Vars(req) |
|
||||||
bucket := vars["bucket"] |
|
||||||
acceptsContentType := getContentType(req) |
|
||||||
|
|
||||||
policy, ok := drivers.Parsepolicy(req.Body) |
|
||||||
if ok == false { |
|
||||||
writeErrorResponse(w, req, InvalidPolicyDocument, acceptsContentType, req.URL.Path) |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
err := server.driver.CreateBucketPolicy(bucket, policy) |
|
||||||
switch err := err.(type) { |
|
||||||
case nil: |
|
||||||
{ |
|
||||||
w.WriteHeader(http.StatusNoContent) |
|
||||||
setCommonHeaders(w, getContentTypeString(acceptsContentType)) |
|
||||||
w.Header().Set("Connection", "keep-alive") |
|
||||||
} |
|
||||||
case drivers.BucketNameInvalid: |
|
||||||
{ |
|
||||||
writeErrorResponse(w, req, InvalidBucketName, acceptsContentType, req.URL.Path) |
|
||||||
} |
|
||||||
case drivers.BucketNotFound: |
|
||||||
{ |
|
||||||
writeErrorResponse(w, req, NoSuchBucket, acceptsContentType, req.URL.Path) |
|
||||||
} |
|
||||||
case drivers.BackendCorrupted: |
|
||||||
{ |
|
||||||
log.Error.Println(err) |
|
||||||
writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path) |
|
||||||
} |
|
||||||
case drivers.ImplementationError: |
|
||||||
{ |
|
||||||
log.Error.Println(err) |
|
||||||
writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// GET Bucket policy
|
|
||||||
// -----------------
|
|
||||||
// This implementation of the GET operation uses the policy subresource
|
|
||||||
// to return the policy of a specified bucket.
|
|
||||||
func (server *minioAPI) getBucketPolicyHandler(w http.ResponseWriter, req *http.Request) { |
|
||||||
vars := mux.Vars(req) |
|
||||||
bucket := vars["bucket"] |
|
||||||
acceptsContentType := getContentType(req) |
|
||||||
|
|
||||||
p, err := server.driver.GetBucketPolicy(bucket) |
|
||||||
switch err := err.(type) { |
|
||||||
case nil: |
|
||||||
{ |
|
||||||
responsePolicy, err := json.Marshal(p) |
|
||||||
if err != nil { |
|
||||||
// log error
|
|
||||||
log.Error.Println(iodine.New(err, nil)) |
|
||||||
writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path) |
|
||||||
return |
|
||||||
} |
|
||||||
setCommonHeaders(w, getContentTypeString(acceptsContentType)) |
|
||||||
w.Header().Set("Connection", "keep-alive") |
|
||||||
w.WriteHeader(http.StatusOK) |
|
||||||
w.Write(responsePolicy) |
|
||||||
} |
|
||||||
case drivers.BucketNameInvalid: |
|
||||||
{ |
|
||||||
writeErrorResponse(w, req, InvalidBucketName, acceptsContentType, req.URL.Path) |
|
||||||
} |
|
||||||
case drivers.BucketNotFound: |
|
||||||
{ |
|
||||||
writeErrorResponse(w, req, NoSuchBucket, acceptsContentType, req.URL.Path) |
|
||||||
} |
|
||||||
case drivers.BucketPolicyNotFound: |
|
||||||
{ |
|
||||||
writeErrorResponse(w, req, NoSuchBucketPolicy, acceptsContentType, req.URL.Path) |
|
||||||
} |
|
||||||
case drivers.BackendCorrupted: |
|
||||||
{ |
|
||||||
log.Error.Println(err) |
|
||||||
writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path) |
|
||||||
} |
|
||||||
case drivers.ImplementationError: |
|
||||||
{ |
|
||||||
log.Error.Println(err) |
|
||||||
writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,199 +0,0 @@ |
|||||||
/* |
|
||||||
* Minimalist Object Storage, (C) 2015 Minio, Inc. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package drivers |
|
||||||
|
|
||||||
import ( |
|
||||||
"encoding/json" |
|
||||||
"io" |
|
||||||
"strings" |
|
||||||
) |
|
||||||
|
|
||||||
// User - canonical
|
|
||||||
type User struct { |
|
||||||
AWS string |
|
||||||
} |
|
||||||
|
|
||||||
// Statement - minio policy statement
|
|
||||||
type Statement struct { |
|
||||||
Sid string |
|
||||||
Effect string |
|
||||||
Principal User |
|
||||||
Action []string |
|
||||||
Resource []string |
|
||||||
// add Condition struct/var TODO - fix it in future if necessary
|
|
||||||
} |
|
||||||
|
|
||||||
// BucketPolicy - minio policy collection
|
|
||||||
type BucketPolicy struct { |
|
||||||
Version string // date in 0000-00-00 format
|
|
||||||
Statement []Statement |
|
||||||
} |
|
||||||
|
|
||||||
// Resource delimiter
|
|
||||||
const ( |
|
||||||
MinioResource = "minio:::" |
|
||||||
) |
|
||||||
|
|
||||||
// TODO support canonical user
|
|
||||||
// Principal delimiter
|
|
||||||
const ( |
|
||||||
MinioPrincipal = "minio::" |
|
||||||
) |
|
||||||
|
|
||||||
// Action map
|
|
||||||
var SupportedActionMap = map[string]bool{ |
|
||||||
"*": true, |
|
||||||
"minio:GetObject": true, |
|
||||||
"minio:ListBucket": true, |
|
||||||
"minio:PutObject": true, |
|
||||||
"minio:CreateBucket": true, |
|
||||||
"minio:GetBucketPolicy": true, |
|
||||||
"minio:DeleteBucketPolicy": true, |
|
||||||
"minio:ListAllMyBuckets": true, |
|
||||||
"minio:PutBucketPolicy": true, |
|
||||||
} |
|
||||||
|
|
||||||
// Effect map
|
|
||||||
var SupportedEffectMap = map[string]bool{ |
|
||||||
"Allow": true, |
|
||||||
"Deny": true, |
|
||||||
} |
|
||||||
|
|
||||||
func isValidAction(action []string) bool { |
|
||||||
for _, a := range action { |
|
||||||
if !SupportedActionMap[a] { |
|
||||||
return false |
|
||||||
} |
|
||||||
} |
|
||||||
return true |
|
||||||
} |
|
||||||
|
|
||||||
func isValidEffect(effect string) bool { |
|
||||||
if SupportedEffectMap[effect] { |
|
||||||
return true |
|
||||||
} |
|
||||||
return false |
|
||||||
} |
|
||||||
|
|
||||||
func isValidResource(resources []string) bool { |
|
||||||
var ok bool |
|
||||||
for _, resource := range resources { |
|
||||||
switch true { |
|
||||||
case strings.HasPrefix(resource, AwsResource): |
|
||||||
bucket := strings.SplitAfter(resource, AwsResource)[1] |
|
||||||
ok = true |
|
||||||
if len(bucket) == 0 { |
|
||||||
ok = false |
|
||||||
} |
|
||||||
case strings.HasPrefix(resource, MinioResource): |
|
||||||
bucket := strings.SplitAfter(resource, MinioResource)[1] |
|
||||||
ok = true |
|
||||||
if len(bucket) == 0 { |
|
||||||
ok = false |
|
||||||
} |
|
||||||
default: |
|
||||||
ok = false |
|
||||||
} |
|
||||||
} |
|
||||||
return ok |
|
||||||
} |
|
||||||
|
|
||||||
func isValidPrincipal(principal string) bool { |
|
||||||
var ok bool |
|
||||||
if principal == "*" { |
|
||||||
return true |
|
||||||
} |
|
||||||
switch true { |
|
||||||
case strings.HasPrefix(principal, AwsPrincipal): |
|
||||||
username := strings.SplitAfter(principal, AwsPrincipal)[1] |
|
||||||
ok = true |
|
||||||
if len(username) == 0 { |
|
||||||
ok = false |
|
||||||
} |
|
||||||
|
|
||||||
case strings.HasPrefix(principal, MinioPrincipal): |
|
||||||
username := strings.SplitAfter(principal, MinioPrincipal)[1] |
|
||||||
ok = true |
|
||||||
if len(username) == 0 { |
|
||||||
ok = false |
|
||||||
} |
|
||||||
default: |
|
||||||
ok = false |
|
||||||
} |
|
||||||
return ok |
|
||||||
} |
|
||||||
|
|
||||||
func parseStatement(statement Statement) bool { |
|
||||||
if len(statement.Sid) == 0 { |
|
||||||
return false |
|
||||||
} |
|
||||||
if len(statement.Effect) == 0 { |
|
||||||
return false |
|
||||||
} |
|
||||||
if !isValidEffect(statement.Effect) { |
|
||||||
return false |
|
||||||
} |
|
||||||
if len(statement.Principal.AWS) == 0 { |
|
||||||
return false |
|
||||||
} |
|
||||||
if !isValidPrincipal(statement.Principal.AWS) { |
|
||||||
return false |
|
||||||
} |
|
||||||
if len(statement.Action) == 0 { |
|
||||||
return false |
|
||||||
} |
|
||||||
if !isValidAction(statement.Action) && !isValidActionS3(statement.Action) { |
|
||||||
return false |
|
||||||
} |
|
||||||
if len(statement.Resource) == 0 { |
|
||||||
return false |
|
||||||
} |
|
||||||
if !isValidResource(statement.Resource) { |
|
||||||
return false |
|
||||||
} |
|
||||||
return true |
|
||||||
} |
|
||||||
|
|
||||||
// Parsepolicy - validate request body is proper JSON and in accordance with policy standards
|
|
||||||
func Parsepolicy(data io.Reader) (BucketPolicy, bool) { |
|
||||||
var policy BucketPolicy |
|
||||||
decoder := json.NewDecoder(data) |
|
||||||
err := decoder.Decode(&policy) |
|
||||||
if err != nil { |
|
||||||
goto error |
|
||||||
} |
|
||||||
if len(policy.Version) == 0 { |
|
||||||
goto error |
|
||||||
} |
|
||||||
_, err = parseDate(policy.Version) |
|
||||||
if err != nil { |
|
||||||
goto error |
|
||||||
} |
|
||||||
if len(policy.Statement) == 0 { |
|
||||||
goto error |
|
||||||
} |
|
||||||
|
|
||||||
for _, statement := range policy.Statement { |
|
||||||
if !parseStatement(statement) { |
|
||||||
goto error |
|
||||||
} |
|
||||||
} |
|
||||||
return policy, true |
|
||||||
|
|
||||||
error: |
|
||||||
return BucketPolicy{}, false |
|
||||||
} |
|
@ -1,52 +0,0 @@ |
|||||||
/* |
|
||||||
* Minimalist Object Storage, (C) 2015 Minio, Inc. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package drivers |
|
||||||
|
|
||||||
// This file implements compatability layer for AWS clients
|
|
||||||
|
|
||||||
// Resource delimiter
|
|
||||||
const ( |
|
||||||
AwsResource = "arn:aws:s3:::" |
|
||||||
) |
|
||||||
|
|
||||||
// TODO support canonical user
|
|
||||||
// Principal delimiter
|
|
||||||
const ( |
|
||||||
AwsPrincipal = "arn:aws:iam::" |
|
||||||
) |
|
||||||
|
|
||||||
// Action map
|
|
||||||
var SupportedActionMapCompat = map[string]bool{ |
|
||||||
"*": true, |
|
||||||
"s3:GetObject": true, |
|
||||||
"s3:ListBucket": true, |
|
||||||
"s3:PutObject": true, |
|
||||||
"s3:CreateBucket": true, |
|
||||||
"s3:GetBucketPolicy": true, |
|
||||||
"s3:DeleteBucketPolicy": true, |
|
||||||
"s3:ListAllMyBuckets": true, |
|
||||||
"s3:PutBucketPolicy": true, |
|
||||||
} |
|
||||||
|
|
||||||
func isValidActionS3(action []string) bool { |
|
||||||
for _, a := range action { |
|
||||||
if !SupportedActionMapCompat[a] { |
|
||||||
return false |
|
||||||
} |
|
||||||
} |
|
||||||
return true |
|
||||||
} |
|
Loading…
Reference in new issue