base handlers

This commit is contained in:
Konstantin Lebedev 2020-12-10 00:03:14 +05:00
parent 03c7953254
commit d7719d0542

View file

@ -2,44 +2,179 @@ package iamapi
import ( import (
"encoding/xml" "encoding/xml"
"fmt"
"github.com/chrislusf/seaweedfs/weed/glog" "github.com/chrislusf/seaweedfs/weed/glog"
"github.com/chrislusf/seaweedfs/weed/pb/iam_pb" "github.com/chrislusf/seaweedfs/weed/pb/iam_pb"
"github.com/chrislusf/seaweedfs/weed/s3api/s3err" "github.com/chrislusf/seaweedfs/weed/s3api/s3err"
"math/rand"
"net/http" "net/http"
"net/url" "net/url"
"time"
// "github.com/aws/aws-sdk-go/aws" // "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" version = "2010-05-08"
charsetUpper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
charset = charsetUpper + "abcdefghijklmnopqrstuvwxyz/"
) )
type ListUsersResponse struct { var seededRand *rand.Rand = rand.New(
XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ ListUsersResponse"` rand.NewSource(time.Now().UnixNano()))
ListUsersResult struct {
Users []*iam.User `xml:"Users>member"` type Response interface {
IsTruncated bool `xml:"IsTruncated"` SetRequestId()
} `xml:"ListUsersResult"` }
type CommonResponse struct {
ResponseMetadata struct { ResponseMetadata struct {
RequestId string `xml:"RequestId"` RequestId string `xml:"RequestId"`
} `xml:"ResponseMetadata"` } `xml:"ResponseMetadata"`
} }
// {'Action': 'CreateUser', 'Version': '2010-05-08', 'UserName': 'Bob'} type ListUsersResponse struct {
// {'Action': 'ListUsers', 'Version': '2010-05-08'} CommonResponse
func (iama *IamApiServer) ListUsers(s3cfg *iam_pb.S3ApiConfiguration, values url.Values) ListUsersResponse { XMLName xml.Name `xml:"https://iam.amazonaws.com/doc/2010-05-08/ ListUsersResponse"`
glog.Info("Do ListUsers") ListUsersResult struct {
resp := ListUsersResponse{} 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 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"`
}
func (r *CommonResponse) SetRequestId() {
r.ResponseMetadata.RequestId = fmt.Sprintf("%d", time.Now().UnixNano())
}
func StringWithCharset(length int, charset string) string {
b := make([]byte, length)
for i := range b {
b[i] = charset[seededRand.Intn(len(charset))]
}
return string(b)
}
func (iama *IamApiServer) ListUsers(s3cfg *iam_pb.S3ApiConfiguration, values url.Values) (resp ListUsersResponse) {
for _, ident := range s3cfg.Identities { for _, ident := range s3cfg.Identities {
resp.ListUsersResult.Users = append(resp.ListUsersResult.Users, &iam.User{UserName: &ident.Name}) resp.ListUsersResult.Users = append(resp.ListUsersResult.Users, &iam.User{UserName: &ident.Name})
} }
return resp return resp
} }
func (iama *IamApiServer) ListAccessKeys(values url.Values) ListUsersResponse { func (iama *IamApiServer) ListAccessKeys(s3cfg *iam_pb.S3ApiConfiguration, values url.Values) (resp ListAccessKeysResponse) {
return ListUsersResponse{} status := iam.StatusTypeActive
for _, ident := range s3cfg.Identities {
for _, cred := range ident.Credentials {
resp.ListAccessKeysResult.AccessKeyMetadata = append(resp.ListAccessKeysResult.AccessKeyMetadata,
&iam.AccessKeyMetadata{UserName: &ident.Name, AccessKeyId: &cred.AccessKey, Status: &status},
)
}
}
return resp
}
func (iama *IamApiServer) CreateUser(s3cfg *iam_pb.S3ApiConfiguration, values url.Values) (resp CreateUserResponse) {
userName := values.Get("UserName")
resp.CreateUserResult.User.UserName = &userName
s3cfg.Identities = append(s3cfg.Identities, &iam_pb.Identity{Name: userName})
return resp
}
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) {
userName := values.Get("UserName")
status := iam.StatusTypeActive
accessKeyId := StringWithCharset(21, charsetUpper)
secretAccessKey := StringWithCharset(42, charset)
resp.CreateAccessKeyResult.AccessKey.AccessKeyId = &accessKeyId
resp.CreateAccessKeyResult.AccessKey.SecretAccessKey = &secretAccessKey
resp.CreateAccessKeyResult.AccessKey.UserName = &userName
resp.CreateAccessKeyResult.AccessKey.Status = &status
changed := false
for _, ident := range s3cfg.Identities {
if userName == ident.Name {
ident.Credentials = append(ident.Credentials,
&iam_pb.Credential{AccessKey: accessKeyId, SecretKey: secretAccessKey})
changed = true
break
}
}
if !changed {
s3cfg.Identities = append(s3cfg.Identities,
&iam_pb.Identity{Name: userName,
Credentials: []*iam_pb.Credential{
{
AccessKey: accessKeyId,
SecretKey: secretAccessKey,
},
},
},
)
}
return resp
}
func (iama *IamApiServer) DeleteAccessKey(s3cfg *iam_pb.S3ApiConfiguration, values url.Values) (resp DeleteAccessKeyResponse) {
userName := values.Get("UserName")
accessKeyId := values.Get("AccessKeyId")
for _, ident := range s3cfg.Identities {
if userName == ident.Name {
for i, cred := range ident.Credentials {
if cred.AccessKey == accessKeyId {
ident.Credentials = append(ident.Credentials[:i], ident.Credentials[i+1:]...)
break
}
}
break
}
}
return resp
} }
func (iama *IamApiServer) DoActions(w http.ResponseWriter, r *http.Request) { func (iama *IamApiServer) DoActions(w http.ResponseWriter, r *http.Request) {
@ -60,7 +195,15 @@ func (iama *IamApiServer) DoActions(w http.ResponseWriter, r *http.Request) {
case "ListUsers": case "ListUsers":
response = iama.ListUsers(s3cfg, values) response = iama.ListUsers(s3cfg, values)
case "ListAccessKeys": case "ListAccessKeys":
response = iama.ListAccessKeys(values) response = iama.ListAccessKeys(s3cfg, values)
case "CreateUser":
response = iama.CreateUser(s3cfg, values)
case "DeleteUser":
response = iama.DeleteUser(s3cfg, values)
case "CreateAccessKey":
response = iama.CreateAccessKey(s3cfg, values)
case "DeleteAccessKey":
response = iama.DeleteAccessKey(s3cfg, values)
default: default:
writeErrorResponse(w, s3err.ErrNotImplemented, r.URL) writeErrorResponse(w, s3err.ErrNotImplemented, r.URL)
return return