mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2024-01-19 02:48:24 +00:00
handler PutUserPolicy
https://docs.aws.amazon.com/IAM/latest/APIReference/API_PutUserPolicy.html
This commit is contained in:
parent
d7719d0542
commit
82b0463fac
|
@ -1,14 +1,18 @@
|
|||
package iamapi
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"github.com/chrislusf/seaweedfs/weed/glog"
|
||||
"github.com/chrislusf/seaweedfs/weed/pb/iam_pb"
|
||||
"github.com/chrislusf/seaweedfs/weed/s3api/s3_constants"
|
||||
"github.com/chrislusf/seaweedfs/weed/s3api/s3err"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
// "github.com/aws/aws-sdk-go/aws"
|
||||
|
@ -21,11 +25,19 @@ const (
|
|||
charset = charsetUpper + "abcdefghijklmnopqrstuvwxyz/"
|
||||
)
|
||||
|
||||
var seededRand *rand.Rand = rand.New(
|
||||
var (
|
||||
seededRand *rand.Rand = rand.New(
|
||||
rand.NewSource(time.Now().UnixNano()))
|
||||
policyDocuments = map[string]*PolicyDocument{}
|
||||
)
|
||||
|
||||
type Response interface {
|
||||
SetRequestId()
|
||||
type PolicyDocument struct {
|
||||
Version string `json:"Version"`
|
||||
Statement []struct {
|
||||
Effect string `json:"Effect"`
|
||||
Action []string `json:"Action"`
|
||||
Resource []string `json:"Resource"`
|
||||
} `json:"Statement"`
|
||||
}
|
||||
|
||||
type CommonResponse struct {
|
||||
|
@ -62,6 +74,14 @@ type DeleteAccessKeyResponse struct {
|
|||
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ DeleteAccessKeyResponse"`
|
||||
}
|
||||
|
||||
type CreatePolicyResponse struct {
|
||||
CommonResponse
|
||||
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ CreatePolicyResponse"`
|
||||
CreatePolicyResult struct {
|
||||
Policy iam.Policy `xml:"Policy"`
|
||||
} `xml:"CreatePolicyResult"`
|
||||
}
|
||||
|
||||
type CreateUserResponse struct {
|
||||
CommonResponse
|
||||
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ CreateUserResponse"`
|
||||
|
@ -78,10 +98,21 @@ type CreateAccessKeyResponse struct {
|
|||
} `xml:"CreateAccessKeyResult"`
|
||||
}
|
||||
|
||||
type PutUserPolicyResponse struct {
|
||||
CommonResponse
|
||||
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ PutUserPolicyResponse"`
|
||||
}
|
||||
|
||||
func (r *CommonResponse) SetRequestId() {
|
||||
r.ResponseMetadata.RequestId = fmt.Sprintf("%d", time.Now().UnixNano())
|
||||
}
|
||||
|
||||
func Hash(s *string) string {
|
||||
h := sha1.New()
|
||||
h.Write([]byte(*s))
|
||||
return fmt.Sprintf("%x", h.Sum(nil))
|
||||
}
|
||||
|
||||
func StringWithCharset(length int, charset string) string {
|
||||
b := make([]byte, length)
|
||||
for i := range b {
|
||||
|
@ -115,6 +146,96 @@ func (iama *IamApiServer) CreateUser(s3cfg *iam_pb.S3ApiConfiguration, values ur
|
|||
s3cfg.Identities = append(s3cfg.Identities, &iam_pb.Identity{Name: userName})
|
||||
return resp
|
||||
}
|
||||
func GetPolicyDocument(policy *string) (policyDocument PolicyDocument, err error) {
|
||||
if err = json.Unmarshal([]byte(*policy), &policyDocument); err != nil {
|
||||
return PolicyDocument{}, err
|
||||
}
|
||||
return policyDocument, err
|
||||
}
|
||||
|
||||
func (iama *IamApiServer) CreatePolicy(s3cfg *iam_pb.S3ApiConfiguration, values url.Values) (resp CreatePolicyResponse, err error) {
|
||||
policyName := values.Get("PolicyName")
|
||||
policyDocumentString := values.Get("PolicyDocument")
|
||||
policyDocument, err := GetPolicyDocument(&policyDocumentString)
|
||||
if err != nil {
|
||||
return CreatePolicyResponse{}, err
|
||||
}
|
||||
policyId := Hash(&policyDocumentString)
|
||||
arn := fmt.Sprintf("arn:aws:iam:::policy/%s", policyName)
|
||||
resp.CreatePolicyResult.Policy.PolicyName = &policyName
|
||||
resp.CreatePolicyResult.Policy.Arn = &arn
|
||||
resp.CreatePolicyResult.Policy.PolicyId = &policyId
|
||||
policyDocuments[policyName] = &policyDocument
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (iama *IamApiServer) PutUserPolicy(s3cfg *iam_pb.S3ApiConfiguration, values url.Values) (resp PutUserPolicyResponse, err error) {
|
||||
userName := values.Get("UserName")
|
||||
policyName := values.Get("PolicyName")
|
||||
policyDocumentString := values.Get("PolicyDocument")
|
||||
policyDocument, err := GetPolicyDocument(&policyDocumentString)
|
||||
if err != nil {
|
||||
return PutUserPolicyResponse{}, err
|
||||
}
|
||||
policyDocuments[policyName] = &policyDocument
|
||||
actions := GetActions(&policyDocument)
|
||||
for _, ident := range s3cfg.Identities {
|
||||
if userName == ident.Name {
|
||||
for _, action := range actions {
|
||||
ident.Actions = append(ident.Actions, action)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func MapAction(action string) string {
|
||||
switch action {
|
||||
case "*":
|
||||
return s3_constants.ACTION_ADMIN
|
||||
case "Put*":
|
||||
return s3_constants.ACTION_WRITE
|
||||
case "Get*":
|
||||
return s3_constants.ACTION_READ
|
||||
case "List*":
|
||||
return s3_constants.ACTION_LIST
|
||||
default:
|
||||
return s3_constants.ACTION_TAGGING
|
||||
}
|
||||
}
|
||||
|
||||
func GetActions(policy *PolicyDocument) (actions []string) {
|
||||
for _, statement := range policy.Statement {
|
||||
if statement.Effect != "Allow" {
|
||||
continue
|
||||
}
|
||||
for _, resource := range statement.Resource {
|
||||
// Parse "arn:aws:s3:::my-bucket/shared/*"
|
||||
res := strings.Split(resource, ":")
|
||||
if len(res) != 6 || res[0] != "arn:" || res[1] != "aws" || res[2] != "s3" {
|
||||
continue
|
||||
}
|
||||
for _, action := range statement.Action {
|
||||
// Parse "s3:Get*"
|
||||
act := strings.Split(action, ":")
|
||||
if len(act) != 2 || act[0] != "s3" {
|
||||
continue
|
||||
}
|
||||
if res[5] == "*" {
|
||||
actions = append(actions, MapAction(act[1]))
|
||||
continue
|
||||
}
|
||||
// Parse my-bucket/shared/*
|
||||
path := strings.Split(res[5], "/")
|
||||
if len(path) != 2 || path[1] != "*" {
|
||||
actions = append(actions, fmt.Sprintf("%s:%s", MapAction(act[1]), path[0]))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return actions
|
||||
}
|
||||
|
||||
func (iama *IamApiServer) DeleteUser(s3cfg *iam_pb.S3ApiConfiguration, values url.Values) (resp DeleteUserResponse) {
|
||||
userName := values.Get("UserName")
|
||||
|
@ -204,6 +325,20 @@ func (iama *IamApiServer) DoActions(w http.ResponseWriter, r *http.Request) {
|
|||
response = iama.CreateAccessKey(s3cfg, values)
|
||||
case "DeleteAccessKey":
|
||||
response = iama.DeleteAccessKey(s3cfg, values)
|
||||
case "CreatePolicy":
|
||||
var err error
|
||||
response, err = iama.CreatePolicy(s3cfg, values)
|
||||
if err != nil {
|
||||
writeErrorResponse(w, s3err.ErrInvalidRequest, r.URL)
|
||||
return
|
||||
}
|
||||
case "PutUserPolicy":
|
||||
var err error
|
||||
response, err = iama.PutUserPolicy(s3cfg, values)
|
||||
if err != nil {
|
||||
writeErrorResponse(w, s3err.ErrInvalidRequest, r.URL)
|
||||
return
|
||||
}
|
||||
default:
|
||||
writeErrorResponse(w, s3err.ErrNotImplemented, r.URL)
|
||||
return
|
||||
|
|
Loading…
Reference in a new issue