iam GetUser

This commit is contained in:
Konstantin Lebedev 2021-03-29 12:01:44 +05:00
parent 40938d6a47
commit 8a95f9c10c
4 changed files with 167 additions and 88 deletions

View file

@ -25,6 +25,8 @@ var (
filerS3Options S3Options filerS3Options S3Options
filerStartWebDav *bool filerStartWebDav *bool
filerWebDavOptions WebDavOption filerWebDavOptions WebDavOption
filerStartIam *bool
filerIamOptions IamOptions
) )
type FilerOptions struct { type FilerOptions struct {
@ -89,6 +91,10 @@ func init() {
filerWebDavOptions.tlsCertificate = cmdFiler.Flag.String("webdav.cert.file", "", "path to the TLS certificate file") filerWebDavOptions.tlsCertificate = cmdFiler.Flag.String("webdav.cert.file", "", "path to the TLS certificate file")
filerWebDavOptions.cacheDir = cmdFiler.Flag.String("webdav.cacheDir", os.TempDir(), "local cache directory for file chunks") filerWebDavOptions.cacheDir = cmdFiler.Flag.String("webdav.cacheDir", os.TempDir(), "local cache directory for file chunks")
filerWebDavOptions.cacheSizeMB = cmdFiler.Flag.Int64("webdav.cacheCapacityMB", 1000, "local cache capacity in MB") filerWebDavOptions.cacheSizeMB = cmdFiler.Flag.Int64("webdav.cacheCapacityMB", 1000, "local cache capacity in MB")
// start iam on filer
filerStartIam = cmdFiler.Flag.Bool("iam", false, "whether to start IAM service")
filerIamOptions.port = cmdFiler.Flag.Int("iam.port", 8111, "iam server http listen port")
} }
var cmdFiler = &Command{ var cmdFiler = &Command{
@ -119,22 +125,33 @@ func runFiler(cmd *Command, args []string) bool {
go stats_collect.StartMetricsServer(*f.metricsHttpPort) go stats_collect.StartMetricsServer(*f.metricsHttpPort)
if *filerStartS3 {
filerAddress := fmt.Sprintf("%s:%d", *f.ip, *f.port) filerAddress := fmt.Sprintf("%s:%d", *f.ip, *f.port)
startDelay := time.Duration(2)
if *filerStartS3 {
filerS3Options.filer = &filerAddress filerS3Options.filer = &filerAddress
go func() { go func() {
time.Sleep(2 * time.Second) time.Sleep(startDelay * time.Second)
filerS3Options.startS3Server() filerS3Options.startS3Server()
}() }()
startDelay++
} }
if *filerStartWebDav { if *filerStartWebDav {
filerAddress := fmt.Sprintf("%s:%d", *f.ip, *f.port)
filerWebDavOptions.filer = &filerAddress filerWebDavOptions.filer = &filerAddress
go func() { go func() {
time.Sleep(2 * time.Second) time.Sleep(startDelay * time.Second)
filerWebDavOptions.startWebDav() filerWebDavOptions.startWebDav()
}() }()
startDelay++
}
if *filerStartIam {
filerIamOptions.filer = &filerAddress
filerIamOptions.masters = f.masters
go func() {
time.Sleep(startDelay * time.Second)
filerIamOptions.startIamServer()
}()
} }
f.startFiler() f.startFiler()

View file

@ -12,6 +12,8 @@ import (
"github.com/chrislusf/seaweedfs/weed/glog" "github.com/chrislusf/seaweedfs/weed/glog"
"github.com/chrislusf/seaweedfs/weed/s3api/s3err" "github.com/chrislusf/seaweedfs/weed/s3api/s3err"
"github.com/aws/aws-sdk-go/service/iam"
) )
type mimeType string type mimeType string
@ -48,6 +50,22 @@ func writeErrorResponse(w http.ResponseWriter, errorCode s3err.ErrorCode, reqURL
writeResponse(w, apiError.HTTPStatusCode, encodedErrorResponse, mimeXML) writeResponse(w, apiError.HTTPStatusCode, encodedErrorResponse, mimeXML)
} }
func writeIamErrorResponse(w http.ResponseWriter, err error, object string, value string) {
errCode := err.Error()
errorResp := ErrorResponse{}
errorResp.Error.Type = "Sender"
errorResp.Error.Code = &errCode
switch errCode {
case iam.ErrCodeNoSuchEntityException:
msg := fmt.Sprintf("The %s with name %s cannot be found.", object, value)
errorResp.Error.Message = &msg
writeResponse(w, http.StatusNotFound, encodeResponse(errorResp), mimeXML)
default:
writeResponse(w, http.StatusInternalServerError, encodeResponse(errorResp), mimeXML)
}
}
func getRESTErrorResponse(err s3err.APIError, resource string) s3err.RESTErrorResponse { func getRESTErrorResponse(err s3err.APIError, resource string) s3err.RESTErrorResponse {
return s3err.RESTErrorResponse{ return s3err.RESTErrorResponse{
Code: err.Code, Code: err.Code,

View file

@ -4,7 +4,6 @@ import (
"bytes" "bytes"
"crypto/sha1" "crypto/sha1"
"encoding/json" "encoding/json"
"encoding/xml"
"fmt" "fmt"
"github.com/chrislusf/seaweedfs/weed/filer" "github.com/chrislusf/seaweedfs/weed/filer"
"github.com/chrislusf/seaweedfs/weed/glog" "github.com/chrislusf/seaweedfs/weed/glog"
@ -19,12 +18,10 @@ import (
"strings" "strings"
"time" "time"
// "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/iam" "github.com/aws/aws-sdk-go/service/iam"
) )
const ( const (
version = "2010-05-08"
charsetUpper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" charsetUpper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
charset = charsetUpper + "abcdefghijklmnopqrstuvwxyz/" charset = charsetUpper + "abcdefghijklmnopqrstuvwxyz/"
) )
@ -44,73 +41,6 @@ type PolicyDocument struct {
} `json:"Statement"` } `json:"Statement"`
} }
type CommonResponse struct {
ResponseMetadata struct {
RequestId string `xml:"RequestId"`
} `xml:"ResponseMetadata"`
}
type ListUsersResponse struct {
CommonResponse
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ ListUsersResponse"`
ListUsersResult struct {
Users []*iam.User `xml:"Users>member"`
IsTruncated bool `xml:"IsTruncated"`
} `xml:"ListUsersResult"`
}
type ListAccessKeysResponse struct {
CommonResponse
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ ListAccessKeysResponse"`
ListAccessKeysResult struct {
AccessKeyMetadata []*iam.AccessKeyMetadata `xml:"AccessKeyMetadata>member"`
IsTruncated bool `xml:"IsTruncated"`
} `xml:"ListAccessKeysResult"`
}
type DeleteUserResponse struct {
CommonResponse
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ DeleteUserResponse"`
}
type DeleteAccessKeyResponse struct {
CommonResponse
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"`
CreateUserResult struct {
User iam.User `xml:"User"`
} `xml:"CreateUserResult"`
}
type CreateAccessKeyResponse struct {
CommonResponse
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ CreateAccessKeyResponse"`
CreateAccessKeyResult struct {
AccessKey iam.AccessKey `xml:"AccessKey"`
} `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 { func Hash(s *string) string {
h := sha1.New() h := sha1.New()
h.Write([]byte(*s)) h.Write([]byte(*s))
@ -150,6 +80,27 @@ func (iama *IamApiServer) CreateUser(s3cfg *iam_pb.S3ApiConfiguration, values ur
s3cfg.Identities = append(s3cfg.Identities, &iam_pb.Identity{Name: userName}) s3cfg.Identities = append(s3cfg.Identities, &iam_pb.Identity{Name: userName})
return resp return resp
} }
func (iama *IamApiServer) DeleteUser(s3cfg *iam_pb.S3ApiConfiguration, userName string) (resp DeleteUserResponse, err error) {
for i, ident := range s3cfg.Identities {
if userName == ident.Name {
ident.Credentials = append(ident.Credentials[:i], ident.Credentials[i+1:]...)
return resp, nil
}
}
return resp, fmt.Errorf(iam.ErrCodeNoSuchEntityException)
}
func (iama *IamApiServer) GetUser(s3cfg *iam_pb.S3ApiConfiguration, userName string) (resp GetUserResponse, err error) {
for _, ident := range s3cfg.Identities {
if userName == ident.Name {
resp.GetUserResult.User = iam.User{UserName: &ident.Name}
return resp, nil
}
}
return resp, fmt.Errorf(iam.ErrCodeNoSuchEntityException)
}
func GetPolicyDocument(policy *string) (policyDocument PolicyDocument, err error) { func GetPolicyDocument(policy *string) (policyDocument PolicyDocument, err error) {
if err = json.Unmarshal([]byte(*policy), &policyDocument); err != nil { if err = json.Unmarshal([]byte(*policy), &policyDocument); err != nil {
return PolicyDocument{}, err return PolicyDocument{}, err
@ -245,17 +196,6 @@ func GetActions(policy *PolicyDocument) (actions []string) {
return actions return actions
} }
func (iama *IamApiServer) DeleteUser(s3cfg *iam_pb.S3ApiConfiguration, values url.Values) (resp DeleteUserResponse) {
userName := values.Get("UserName")
for i, ident := range s3cfg.Identities {
if userName == ident.Name {
ident.Credentials = append(ident.Credentials[:i], ident.Credentials[i+1:]...)
break
}
}
return resp
}
func (iama *IamApiServer) CreateAccessKey(s3cfg *iam_pb.S3ApiConfiguration, values url.Values) (resp CreateAccessKeyResponse) { func (iama *IamApiServer) CreateAccessKey(s3cfg *iam_pb.S3ApiConfiguration, values url.Values) (resp CreateAccessKeyResponse) {
userName := values.Get("UserName") userName := values.Get("UserName")
status := iam.StatusTypeActive status := iam.StatusTypeActive
@ -320,6 +260,7 @@ func (iama *IamApiServer) DoActions(w http.ResponseWriter, r *http.Request) {
glog.Info("values ", values) glog.Info("values ", values)
var response interface{} var response interface{}
var err error
changed := true changed := true
switch r.Form.Get("Action") { switch r.Form.Get("Action") {
case "ListUsers": case "ListUsers":
@ -330,21 +271,31 @@ func (iama *IamApiServer) DoActions(w http.ResponseWriter, r *http.Request) {
changed = false changed = false
case "CreateUser": case "CreateUser":
response = iama.CreateUser(s3cfg, values) response = iama.CreateUser(s3cfg, values)
case "GetUser":
userName := values.Get("UserName")
response, err = iama.GetUser(s3cfg, userName)
if err != nil {
writeIamErrorResponse(w, err, "user", userName)
return
}
case "DeleteUser": case "DeleteUser":
response = iama.DeleteUser(s3cfg, values) userName := values.Get("UserName")
response, err = iama.DeleteUser(s3cfg, userName)
if err != nil {
writeIamErrorResponse(w, err, "user", userName)
return
}
case "CreateAccessKey": case "CreateAccessKey":
response = iama.CreateAccessKey(s3cfg, values) response = iama.CreateAccessKey(s3cfg, values)
case "DeleteAccessKey": case "DeleteAccessKey":
response = iama.DeleteAccessKey(s3cfg, values) response = iama.DeleteAccessKey(s3cfg, values)
case "CreatePolicy": case "CreatePolicy":
var err error
response, err = iama.CreatePolicy(s3cfg, values) response, err = iama.CreatePolicy(s3cfg, values)
if err != nil { if err != nil {
writeErrorResponse(w, s3err.ErrInvalidRequest, r.URL) writeErrorResponse(w, s3err.ErrInvalidRequest, r.URL)
return return
} }
case "PutUserPolicy": case "PutUserPolicy":
var err error
response, err = iama.PutUserPolicy(s3cfg, values) response, err = iama.PutUserPolicy(s3cfg, values)
if err != nil { if err != nil {
writeErrorResponse(w, s3err.ErrInvalidRequest, r.URL) writeErrorResponse(w, s3err.ErrInvalidRequest, r.URL)

View file

@ -0,0 +1,93 @@
package iamapi
import (
"encoding/xml"
"fmt"
"time"
"github.com/aws/aws-sdk-go/service/iam"
)
type CommonResponse struct {
ResponseMetadata struct {
RequestId string `xml:"RequestId"`
} `xml:"ResponseMetadata"`
}
type ListUsersResponse struct {
CommonResponse
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ ListUsersResponse"`
ListUsersResult struct {
Users []*iam.User `xml:"Users>member"`
IsTruncated bool `xml:"IsTruncated"`
} `xml:"ListUsersResult"`
}
type ListAccessKeysResponse struct {
CommonResponse
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ ListAccessKeysResponse"`
ListAccessKeysResult struct {
AccessKeyMetadata []*iam.AccessKeyMetadata `xml:"AccessKeyMetadata>member"`
IsTruncated bool `xml:"IsTruncated"`
} `xml:"ListAccessKeysResult"`
}
type DeleteAccessKeyResponse struct {
CommonResponse
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"`
CreateUserResult struct {
User iam.User `xml:"User"`
} `xml:"CreateUserResult"`
}
type DeleteUserResponse struct {
CommonResponse
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ DeleteUserResponse"`
}
type GetUserResponse struct {
CommonResponse
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ GetUserResponse"`
GetUserResult struct {
User iam.User `xml:"User"`
} `xml:"GetUserResult"`
}
type CreateAccessKeyResponse struct {
CommonResponse
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ CreateAccessKeyResponse"`
CreateAccessKeyResult struct {
AccessKey iam.AccessKey `xml:"AccessKey"`
} `xml:"CreateAccessKeyResult"`
}
type PutUserPolicyResponse struct {
CommonResponse
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ PutUserPolicyResponse"`
}
type ErrorResponse struct {
CommonResponse
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ ErrorResponse"`
Error struct {
iam.ErrorDetails
Type string `xml:"Type"`
} `xml:"Error"`
}
func (r *CommonResponse) SetRequestId() {
r.ResponseMetadata.RequestId = fmt.Sprintf("%d", time.Now().UnixNano())
}