mirror of
https://github.com/minio/minio.git
synced 2024-12-24 22:25:54 -05:00
Add MakeBucket API.
This commit is contained in:
parent
3f1c4bb4b0
commit
432a073e6b
@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/dgrijalva/jwt-go"
|
jwtgo "github.com/dgrijalva/jwt-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
type authHandler struct {
|
type authHandler struct {
|
||||||
@ -25,12 +25,12 @@ func (h authHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
h.handler.ServeHTTP(w, r)
|
h.handler.ServeHTTP(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
authBackend := InitJWT()
|
jwt := InitJWT()
|
||||||
token, err := jwt.ParseFromRequest(r, func(token *jwt.Token) (interface{}, error) {
|
token, err := jwtgo.ParseFromRequest(r, func(token *jwtgo.Token) (interface{}, error) {
|
||||||
if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
|
if _, ok := token.Method.(*jwtgo.SigningMethodRSA); !ok {
|
||||||
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
|
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
|
||||||
}
|
}
|
||||||
return authBackend.PublicKey, nil
|
return jwt.PublicKey, nil
|
||||||
})
|
})
|
||||||
if err != nil || !token.Valid {
|
if err != nil || !token.Valid {
|
||||||
w.WriteHeader(http.StatusUnauthorized)
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
30
jwt.go
30
jwt.go
@ -11,10 +11,12 @@ import (
|
|||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// JWTAuthBackend - jwt auth backend
|
// JWT - jwt auth backend
|
||||||
type JWTAuthBackend struct {
|
type JWT struct {
|
||||||
privateKey *rsa.PrivateKey
|
privateKey *rsa.PrivateKey
|
||||||
PublicKey *rsa.PublicKey
|
PublicKey *rsa.PublicKey
|
||||||
|
accessKeyID string
|
||||||
|
secretAccessKey string
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -23,16 +25,22 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// InitJWT - init.
|
// InitJWT - init.
|
||||||
func InitJWT() *JWTAuthBackend {
|
func InitJWT() *JWT {
|
||||||
authBackendInstance := &JWTAuthBackend{
|
jwt := &JWT{
|
||||||
privateKey: getPrivateKey(),
|
privateKey: getPrivateKey(),
|
||||||
PublicKey: getPublicKey(),
|
PublicKey: getPublicKey(),
|
||||||
}
|
}
|
||||||
return authBackendInstance
|
config, err := loadConfigV2()
|
||||||
|
fatalIf(err.Trace("JWT"), "Unable to load configuration file.", nil)
|
||||||
|
|
||||||
|
// Save access, secret keys.
|
||||||
|
jwt.accessKeyID = config.Credentials.AccessKeyID
|
||||||
|
jwt.secretAccessKey = config.Credentials.SecretAccessKey
|
||||||
|
return jwt
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateToken -
|
// GenerateToken -
|
||||||
func (b *JWTAuthBackend) GenerateToken(userName string) (string, error) {
|
func (b *JWT) GenerateToken(userName string) (string, error) {
|
||||||
token := jwt.New(jwt.SigningMethodRS512)
|
token := jwt.New(jwt.SigningMethodRS512)
|
||||||
token.Claims["exp"] = time.Now().Add(time.Hour * time.Duration(jwtExpirationDelta)).Unix()
|
token.Claims["exp"] = time.Now().Add(time.Hour * time.Duration(jwtExpirationDelta)).Unix()
|
||||||
token.Claims["iat"] = time.Now().Unix()
|
token.Claims["iat"] = time.Now().Unix()
|
||||||
@ -45,16 +53,16 @@ func (b *JWTAuthBackend) GenerateToken(userName string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Authenticate -
|
// Authenticate -
|
||||||
func (b *JWTAuthBackend) Authenticate(args *LoginArgs, accessKeyID, secretAccessKey string) bool {
|
func (b *JWT) Authenticate(args *LoginArgs) bool {
|
||||||
hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(secretAccessKey), 10)
|
hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(b.secretAccessKey), 10)
|
||||||
if args.Username == accessKeyID {
|
if args.Username == b.accessKeyID {
|
||||||
return bcrypt.CompareHashAndPassword(hashedPassword, []byte(args.Password)) == nil
|
return bcrypt.CompareHashAndPassword(hashedPassword, []byte(args.Password)) == nil
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
func (b *JWTAuthBackend) getTokenRemainingValidity(timestamp interface{}) int {
|
func (b *JWT) getTokenRemainingValidity(timestamp interface{}) int {
|
||||||
if validity, ok := timestamp.(float64); ok {
|
if validity, ok := timestamp.(float64); ok {
|
||||||
tm := time.Unix(int64(validity), 0)
|
tm := time.Unix(int64(validity), 0)
|
||||||
remainer := tm.Sub(time.Now())
|
remainer := tm.Sub(time.Now())
|
||||||
@ -66,7 +74,7 @@ func (b *JWTAuthBackend) getTokenRemainingValidity(timestamp interface{}) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Logout - logout is not implemented yet.
|
// Logout - logout is not implemented yet.
|
||||||
func (b *JWTAuthBackend) Logout(tokenString string) error {
|
func (b *JWT) Logout(tokenString string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
30
routers.go
30
routers.go
@ -17,27 +17,35 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
router "github.com/gorilla/mux"
|
router "github.com/gorilla/mux"
|
||||||
jsonrpc "github.com/gorilla/rpc/v2"
|
jsonrpc "github.com/gorilla/rpc/v2"
|
||||||
"github.com/gorilla/rpc/v2/json"
|
"github.com/gorilla/rpc/v2/json"
|
||||||
|
"github.com/minio/minio-go"
|
||||||
|
"github.com/minio/minio-xl/pkg/probe"
|
||||||
"github.com/minio/minio/pkg/fs"
|
"github.com/minio/minio/pkg/fs"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CloudStorageAPI container for S3 compatible API.
|
// CloudStorageAPI container for S3 compatible API.
|
||||||
type CloudStorageAPI struct {
|
type CloudStorageAPI struct {
|
||||||
|
// Do not check for incoming signatures, allow all requests.
|
||||||
|
Anonymous bool
|
||||||
|
// Once true log all incoming requests.
|
||||||
|
AccessLog bool
|
||||||
|
// Filesystem instance.
|
||||||
Filesystem fs.Filesystem
|
Filesystem fs.Filesystem
|
||||||
Anonymous bool // do not checking for incoming signatures, allow all requests
|
|
||||||
AccessLog bool // if true log all incoming request
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WebAPI container for Web API.
|
// WebAPI container for Web API.
|
||||||
type WebAPI struct {
|
type WebAPI struct {
|
||||||
|
// Do not check for incoming authorization header.
|
||||||
Anonymous bool
|
Anonymous bool
|
||||||
|
// Once true log all incoming request.
|
||||||
AccessLog bool
|
AccessLog bool
|
||||||
AccessKeyID string
|
// Minio client instance.
|
||||||
SecretAccessKey string
|
Client minio.CloudStorageClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func getWebAPIHandler(web *WebAPI) http.Handler {
|
func getWebAPIHandler(web *WebAPI) http.Handler {
|
||||||
@ -100,12 +108,22 @@ func registerCloudStorageAPI(mux *router.Router, a CloudStorageAPI) {
|
|||||||
|
|
||||||
// getNewWebAPI instantiate a new WebAPI.
|
// getNewWebAPI instantiate a new WebAPI.
|
||||||
func getNewWebAPI(conf cloudServerConfig) *WebAPI {
|
func getNewWebAPI(conf cloudServerConfig) *WebAPI {
|
||||||
|
// Split host port.
|
||||||
|
_, port, e := net.SplitHostPort(conf.Address)
|
||||||
|
fatalIf(probe.NewError(e), "Unable to parse web addess.", nil)
|
||||||
|
|
||||||
|
// Default host to 'localhost'.
|
||||||
|
host := "localhost"
|
||||||
|
|
||||||
|
// Initialize minio client for AWS Signature Version '4'
|
||||||
|
client, e := minio.NewV4(net.JoinHostPort(host, port), conf.AccessKeyID, conf.SecretAccessKey, true)
|
||||||
|
fatalIf(probe.NewError(e), "Unable to initialize minio client", nil)
|
||||||
|
|
||||||
web := &WebAPI{
|
web := &WebAPI{
|
||||||
Anonymous: conf.Anonymous,
|
Anonymous: conf.Anonymous,
|
||||||
AccessLog: conf.AccessLog,
|
AccessLog: conf.AccessLog,
|
||||||
|
Client: client,
|
||||||
}
|
}
|
||||||
web.AccessKeyID = conf.AccessKeyID
|
|
||||||
web.SecretAccessKey = conf.SecretAccessKey
|
|
||||||
return web
|
return web
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// MakeBucketArgs - make bucket args.
|
||||||
|
type MakeBucketArgs struct {
|
||||||
|
BucketName string `json:"bucketName"`
|
||||||
|
}
|
||||||
|
|
||||||
// ListBucketsArgs - list bucket args.
|
// ListBucketsArgs - list bucket args.
|
||||||
type ListBucketsArgs struct{}
|
type ListBucketsArgs struct{}
|
||||||
|
|
||||||
@ -9,6 +16,24 @@ type ListObjectsArgs struct {
|
|||||||
Prefix string `json:"prefix"`
|
Prefix string `json:"prefix"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BucketInfo container for list buckets metadata.
|
||||||
|
type BucketInfo struct {
|
||||||
|
// The name of the bucket.
|
||||||
|
Name string `json:"name"`
|
||||||
|
// Date the bucket was created.
|
||||||
|
CreationDate time.Time `json:"creationDate"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObjectInfo container for list objects metadata.
|
||||||
|
type ObjectInfo struct {
|
||||||
|
// Name of the object
|
||||||
|
Key string `json:"name"`
|
||||||
|
// Date and time the object was last modified.
|
||||||
|
LastModified time.Time `json:"lastModified"`
|
||||||
|
// Size in bytes of the object.
|
||||||
|
Size int64 `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
// GetObjectURLArgs - get object url.
|
// GetObjectURLArgs - get object url.
|
||||||
type GetObjectURLArgs struct {
|
type GetObjectURLArgs struct {
|
||||||
BucketName string `json:"bucketName"`
|
BucketName string `json:"bucketName"`
|
||||||
|
@ -5,17 +5,16 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/dgrijalva/jwt-go"
|
jwtgo "github.com/dgrijalva/jwt-go"
|
||||||
"github.com/minio/minio-go"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func isAuthenticated(req *http.Request) bool {
|
func isAuthenticated(req *http.Request) bool {
|
||||||
authBackend := InitJWT()
|
jwt := InitJWT()
|
||||||
tokenRequest, err := jwt.ParseFromRequest(req, func(token *jwt.Token) (interface{}, error) {
|
tokenRequest, err := jwtgo.ParseFromRequest(req, func(token *jwtgo.Token) (interface{}, error) {
|
||||||
if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
|
if _, ok := token.Method.(*jwtgo.SigningMethodRSA); !ok {
|
||||||
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
|
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
|
||||||
}
|
}
|
||||||
return authBackend.PublicKey, nil
|
return jwt.PublicKey, nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
@ -23,43 +22,50 @@ func isAuthenticated(req *http.Request) bool {
|
|||||||
return tokenRequest.Valid
|
return tokenRequest.Valid
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListBuckets - list buckets api.
|
// MakeBucket - make a bucket.
|
||||||
func (web *WebAPI) ListBuckets(r *http.Request, args *ListBucketsArgs, reply *[]minio.BucketInfo) error {
|
func (web *WebAPI) MakeBucket(r *http.Request, args *MakeBucketArgs, reply *string) error {
|
||||||
if !isAuthenticated(r) {
|
if !isAuthenticated(r) {
|
||||||
return errUnAuthorizedRequest
|
return errUnAuthorizedRequest
|
||||||
}
|
}
|
||||||
client, err := minio.New("localhost:9000", web.AccessKeyID, web.SecretAccessKey, true)
|
return web.Client.MakeBucket(args.BucketName, "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListBuckets - list buckets api.
|
||||||
|
func (web *WebAPI) ListBuckets(r *http.Request, args *ListBucketsArgs, reply *[]BucketInfo) error {
|
||||||
|
if !isAuthenticated(r) {
|
||||||
|
return errUnAuthorizedRequest
|
||||||
|
}
|
||||||
|
buckets, err := web.Client.ListBuckets()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
buckets, err := client.ListBuckets()
|
for _, bucket := range buckets {
|
||||||
if err != nil {
|
*reply = append(*reply, BucketInfo{
|
||||||
return err
|
Name: bucket.Name,
|
||||||
|
CreationDate: bucket.CreationDate,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
*reply = buckets
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListObjects - list objects api.
|
// ListObjects - list objects api.
|
||||||
func (web *WebAPI) ListObjects(r *http.Request, args *ListObjectsArgs, reply *[]minio.ObjectInfo) error {
|
func (web *WebAPI) ListObjects(r *http.Request, args *ListObjectsArgs, reply *[]ObjectInfo) error {
|
||||||
if !isAuthenticated(r) {
|
if !isAuthenticated(r) {
|
||||||
return errUnAuthorizedRequest
|
return errUnAuthorizedRequest
|
||||||
}
|
}
|
||||||
client, err := minio.New("localhost:9000", web.AccessKeyID, web.SecretAccessKey, true)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
doneCh := make(chan struct{})
|
doneCh := make(chan struct{})
|
||||||
defer close(doneCh)
|
defer close(doneCh)
|
||||||
|
|
||||||
var objects []minio.ObjectInfo
|
for object := range web.Client.ListObjects(args.BucketName, args.Prefix, false, doneCh) {
|
||||||
for object := range client.ListObjects(args.BucketName, args.Prefix, false, doneCh) {
|
|
||||||
if object.Err != nil {
|
if object.Err != nil {
|
||||||
return object.Err
|
return object.Err
|
||||||
}
|
}
|
||||||
objects = append(objects, object)
|
*reply = append(*reply, ObjectInfo{
|
||||||
|
Key: object.Key,
|
||||||
|
LastModified: object.LastModified,
|
||||||
|
Size: object.Size,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
*reply = objects
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,11 +74,7 @@ func (web *WebAPI) GetObjectURL(r *http.Request, args *GetObjectURLArgs, reply *
|
|||||||
if !isAuthenticated(r) {
|
if !isAuthenticated(r) {
|
||||||
return errUnAuthorizedRequest
|
return errUnAuthorizedRequest
|
||||||
}
|
}
|
||||||
client, err := minio.New("localhost:9000", web.AccessKeyID, web.SecretAccessKey, true)
|
urlStr, err := web.Client.PresignedGetObject(args.BucketName, args.ObjectName, time.Duration(60*60)*time.Second)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
urlStr, err := client.PresignedGetObject(args.BucketName, args.ObjectName, time.Duration(60*60)*time.Second)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -82,9 +84,9 @@ func (web *WebAPI) GetObjectURL(r *http.Request, args *GetObjectURLArgs, reply *
|
|||||||
|
|
||||||
// Login - user login handler.
|
// Login - user login handler.
|
||||||
func (web *WebAPI) Login(r *http.Request, args *LoginArgs, reply *AuthToken) error {
|
func (web *WebAPI) Login(r *http.Request, args *LoginArgs, reply *AuthToken) error {
|
||||||
authBackend := InitJWT()
|
jwt := InitJWT()
|
||||||
if authBackend.Authenticate(args, web.AccessKeyID, web.SecretAccessKey) {
|
if jwt.Authenticate(args) {
|
||||||
token, err := authBackend.GenerateToken(args.Username)
|
token, err := jwt.GenerateToken(args.Username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -97,8 +99,8 @@ func (web *WebAPI) Login(r *http.Request, args *LoginArgs, reply *AuthToken) err
|
|||||||
// RefreshToken - refresh token handler.
|
// RefreshToken - refresh token handler.
|
||||||
func (web *WebAPI) RefreshToken(r *http.Request, args *LoginArgs, reply *AuthToken) error {
|
func (web *WebAPI) RefreshToken(r *http.Request, args *LoginArgs, reply *AuthToken) error {
|
||||||
if isAuthenticated(r) {
|
if isAuthenticated(r) {
|
||||||
authBackend := InitJWT()
|
jwt := InitJWT()
|
||||||
token, err := authBackend.GenerateToken(args.Username)
|
token, err := jwt.GenerateToken(args.Username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -111,9 +113,9 @@ func (web *WebAPI) RefreshToken(r *http.Request, args *LoginArgs, reply *AuthTok
|
|||||||
// Logout - user logout.
|
// Logout - user logout.
|
||||||
func (web *WebAPI) Logout(r *http.Request, arg *string, reply *string) error {
|
func (web *WebAPI) Logout(r *http.Request, arg *string, reply *string) error {
|
||||||
if isAuthenticated(r) {
|
if isAuthenticated(r) {
|
||||||
authBackend := InitJWT()
|
jwt := InitJWT()
|
||||||
tokenString := r.Header.Get("Authorization")
|
tokenString := r.Header.Get("Authorization")
|
||||||
if err := authBackend.Logout(tokenString); err != nil {
|
if err := jwt.Logout(tokenString); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
Loading…
Reference in New Issue
Block a user