Add MakeBucket API.

This commit is contained in:
Harshavardhana 2016-01-24 22:26:53 -08:00
parent 3f1c4bb4b0
commit 432a073e6b
5 changed files with 113 additions and 60 deletions

View File

@ -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
View File

@ -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
} }

View File

@ -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
} }

View File

@ -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"`

View File

@ -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