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"
"net/http"
"github.com/dgrijalva/jwt-go"
jwtgo "github.com/dgrijalva/jwt-go"
)
type authHandler struct {
@ -25,12 +25,12 @@ func (h authHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h.handler.ServeHTTP(w, r)
return
}
authBackend := InitJWT()
token, err := jwt.ParseFromRequest(r, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
jwt := InitJWT()
token, err := jwtgo.ParseFromRequest(r, func(token *jwtgo.Token) (interface{}, error) {
if _, ok := token.Method.(*jwtgo.SigningMethodRSA); !ok {
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
}
return authBackend.PublicKey, nil
return jwt.PublicKey, nil
})
if err != nil || !token.Valid {
w.WriteHeader(http.StatusUnauthorized)

34
jwt.go
View File

@ -11,10 +11,12 @@ import (
"golang.org/x/crypto/bcrypt"
)
// JWTAuthBackend - jwt auth backend
type JWTAuthBackend struct {
privateKey *rsa.PrivateKey
PublicKey *rsa.PublicKey
// JWT - jwt auth backend
type JWT struct {
privateKey *rsa.PrivateKey
PublicKey *rsa.PublicKey
accessKeyID string
secretAccessKey string
}
const (
@ -23,16 +25,22 @@ const (
)
// InitJWT - init.
func InitJWT() *JWTAuthBackend {
authBackendInstance := &JWTAuthBackend{
func InitJWT() *JWT {
jwt := &JWT{
privateKey: getPrivateKey(),
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 -
func (b *JWTAuthBackend) GenerateToken(userName string) (string, error) {
func (b *JWT) GenerateToken(userName string) (string, error) {
token := jwt.New(jwt.SigningMethodRS512)
token.Claims["exp"] = time.Now().Add(time.Hour * time.Duration(jwtExpirationDelta)).Unix()
token.Claims["iat"] = time.Now().Unix()
@ -45,16 +53,16 @@ func (b *JWTAuthBackend) GenerateToken(userName string) (string, error) {
}
// Authenticate -
func (b *JWTAuthBackend) Authenticate(args *LoginArgs, accessKeyID, secretAccessKey string) bool {
hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(secretAccessKey), 10)
if args.Username == accessKeyID {
func (b *JWT) Authenticate(args *LoginArgs) bool {
hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(b.secretAccessKey), 10)
if args.Username == b.accessKeyID {
return bcrypt.CompareHashAndPassword(hashedPassword, []byte(args.Password)) == nil
}
return false
}
//
func (b *JWTAuthBackend) getTokenRemainingValidity(timestamp interface{}) int {
func (b *JWT) getTokenRemainingValidity(timestamp interface{}) int {
if validity, ok := timestamp.(float64); ok {
tm := time.Unix(int64(validity), 0)
remainer := tm.Sub(time.Now())
@ -66,7 +74,7 @@ func (b *JWTAuthBackend) getTokenRemainingValidity(timestamp interface{}) int {
}
// Logout - logout is not implemented yet.
func (b *JWTAuthBackend) Logout(tokenString string) error {
func (b *JWT) Logout(tokenString string) error {
return nil
}

View File

@ -17,27 +17,35 @@
package main
import (
"net"
"net/http"
router "github.com/gorilla/mux"
jsonrpc "github.com/gorilla/rpc/v2"
"github.com/gorilla/rpc/v2/json"
"github.com/minio/minio-go"
"github.com/minio/minio-xl/pkg/probe"
"github.com/minio/minio/pkg/fs"
)
// CloudStorageAPI container for S3 compatible API.
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
Anonymous bool // do not checking for incoming signatures, allow all requests
AccessLog bool // if true log all incoming request
}
// WebAPI container for Web API.
type WebAPI struct {
Anonymous bool
AccessLog bool
AccessKeyID string
SecretAccessKey string
// Do not check for incoming authorization header.
Anonymous bool
// Once true log all incoming request.
AccessLog bool
// Minio client instance.
Client minio.CloudStorageClient
}
func getWebAPIHandler(web *WebAPI) http.Handler {
@ -100,12 +108,22 @@ func registerCloudStorageAPI(mux *router.Router, a CloudStorageAPI) {
// getNewWebAPI instantiate a new 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{
Anonymous: conf.Anonymous,
AccessLog: conf.AccessLog,
Client: client,
}
web.AccessKeyID = conf.AccessKeyID
web.SecretAccessKey = conf.SecretAccessKey
return web
}

View File

@ -1,5 +1,12 @@
package main
import "time"
// MakeBucketArgs - make bucket args.
type MakeBucketArgs struct {
BucketName string `json:"bucketName"`
}
// ListBucketsArgs - list bucket args.
type ListBucketsArgs struct{}
@ -9,6 +16,24 @@ type ListObjectsArgs struct {
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.
type GetObjectURLArgs struct {
BucketName string `json:"bucketName"`

View File

@ -5,17 +5,16 @@ import (
"net/http"
"time"
"github.com/dgrijalva/jwt-go"
"github.com/minio/minio-go"
jwtgo "github.com/dgrijalva/jwt-go"
)
func isAuthenticated(req *http.Request) bool {
authBackend := InitJWT()
tokenRequest, err := jwt.ParseFromRequest(req, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
jwt := InitJWT()
tokenRequest, err := jwtgo.ParseFromRequest(req, func(token *jwtgo.Token) (interface{}, error) {
if _, ok := token.Method.(*jwtgo.SigningMethodRSA); !ok {
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
}
return authBackend.PublicKey, nil
return jwt.PublicKey, nil
})
if err != nil {
return false
@ -23,43 +22,50 @@ func isAuthenticated(req *http.Request) bool {
return tokenRequest.Valid
}
// ListBuckets - list buckets api.
func (web *WebAPI) ListBuckets(r *http.Request, args *ListBucketsArgs, reply *[]minio.BucketInfo) error {
// MakeBucket - make a bucket.
func (web *WebAPI) MakeBucket(r *http.Request, args *MakeBucketArgs, reply *string) error {
if !isAuthenticated(r) {
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 {
return err
}
buckets, err := client.ListBuckets()
if err != nil {
return err
for _, bucket := range buckets {
*reply = append(*reply, BucketInfo{
Name: bucket.Name,
CreationDate: bucket.CreationDate,
})
}
*reply = buckets
return nil
}
// 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) {
return errUnAuthorizedRequest
}
client, err := minio.New("localhost:9000", web.AccessKeyID, web.SecretAccessKey, true)
if err != nil {
return err
}
doneCh := make(chan struct{})
defer close(doneCh)
var objects []minio.ObjectInfo
for object := range client.ListObjects(args.BucketName, args.Prefix, false, doneCh) {
for object := range web.Client.ListObjects(args.BucketName, args.Prefix, false, doneCh) {
if object.Err != nil {
return object.Err
}
objects = append(objects, object)
*reply = append(*reply, ObjectInfo{
Key: object.Key,
LastModified: object.LastModified,
Size: object.Size,
})
}
*reply = objects
return nil
}
@ -68,11 +74,7 @@ func (web *WebAPI) GetObjectURL(r *http.Request, args *GetObjectURLArgs, reply *
if !isAuthenticated(r) {
return errUnAuthorizedRequest
}
client, err := minio.New("localhost:9000", web.AccessKeyID, web.SecretAccessKey, true)
if err != nil {
return err
}
urlStr, err := client.PresignedGetObject(args.BucketName, args.ObjectName, time.Duration(60*60)*time.Second)
urlStr, err := web.Client.PresignedGetObject(args.BucketName, args.ObjectName, time.Duration(60*60)*time.Second)
if err != nil {
return err
}
@ -82,9 +84,9 @@ func (web *WebAPI) GetObjectURL(r *http.Request, args *GetObjectURLArgs, reply *
// Login - user login handler.
func (web *WebAPI) Login(r *http.Request, args *LoginArgs, reply *AuthToken) error {
authBackend := InitJWT()
if authBackend.Authenticate(args, web.AccessKeyID, web.SecretAccessKey) {
token, err := authBackend.GenerateToken(args.Username)
jwt := InitJWT()
if jwt.Authenticate(args) {
token, err := jwt.GenerateToken(args.Username)
if err != nil {
return err
}
@ -97,8 +99,8 @@ func (web *WebAPI) Login(r *http.Request, args *LoginArgs, reply *AuthToken) err
// RefreshToken - refresh token handler.
func (web *WebAPI) RefreshToken(r *http.Request, args *LoginArgs, reply *AuthToken) error {
if isAuthenticated(r) {
authBackend := InitJWT()
token, err := authBackend.GenerateToken(args.Username)
jwt := InitJWT()
token, err := jwt.GenerateToken(args.Username)
if err != nil {
return err
}
@ -111,9 +113,9 @@ func (web *WebAPI) RefreshToken(r *http.Request, args *LoginArgs, reply *AuthTok
// Logout - user logout.
func (web *WebAPI) Logout(r *http.Request, arg *string, reply *string) error {
if isAuthenticated(r) {
authBackend := InitJWT()
jwt := InitJWT()
tokenString := r.Header.Get("Authorization")
if err := authBackend.Logout(tokenString); err != nil {
if err := jwt.Logout(tokenString); err != nil {
return err
}
return nil