Skip to content

Commit

Permalink
s3 auth
Browse files Browse the repository at this point in the history
  • Loading branch information
aldor007 committed Oct 8, 2017
1 parent 33fc913 commit 8deda1b
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 14 deletions.
1 change: 1 addition & 0 deletions cmd/mort.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func main() {
// Echo instance
e := echo.New()

e.Use(mort.S3AuthMiddleware(imgConfig))
e.Use(mort.S3Middleware(imgConfig))

// Route => handler
Expand Down
21 changes: 21 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
type Config struct {
Buckets map[string]Bucket `yaml:"buckets"`
Headers []HeaderYaml `yaml:"headers"`
accessKeyBucket map[string][] string
}

var instance *Config
Expand Down Expand Up @@ -38,6 +39,7 @@ func (self *Config) Load(filePath string) {

errYaml := yaml.Unmarshal([]byte(data), self)

self.accessKeyBucket = make(map[string][]string)
for name, bucket := range self.Buckets {
if bucket.Transform != nil {
if bucket.Transform.Path != "" {
Expand All @@ -48,11 +50,30 @@ func (self *Config) Load(filePath string) {
bucket.Transform.ParentStorage = "basic"
}
}

bucket.Name = name
self.Buckets[name] = bucket
for _, key := range bucket.Keys {
//if self.accessKeyBucket[key.AccessKey] == nil {
// self.accessKeyBucket[key.AccessKey] = make([]stri
//}

self.accessKeyBucket[key.AccessKey] = append(self.accessKeyBucket[key.AccessKey], name)
}
}

if errYaml != nil {
panic(errYaml)
}

}

func (c *Config) BucketsByAccessKey(accessKey string) []Bucket {
list := c.accessKeyBucket[accessKey]
var buckets []Bucket = make([]Bucket, len(list))
for _, name := range list {
buckets = append(buckets, c.Buckets[name])
}

return buckets
}
1 change: 1 addition & 0 deletions config/yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ type Bucket struct {
Transform *TransformYaml `yaml:"transform",omitempty`
Storages StorageTypes `yaml:"storages"`
Keys []S3Key `yaml:"keys"`
Name string
}

type HeaderYaml struct {
Expand Down
155 changes: 141 additions & 14 deletions s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,38 @@ import (
"mort/config"
"github.com/labstack/echo"
//"github.com/crunchytom/go-aws-auth"
//awsv4 "github.com/aws/aws-sdk-go/aws/signer/v4"
//awsv4 "githubBucketcom/aws/aws-sdk-go/aws/signer/v4"
"regexp"
"strings"
"errors"
"github.com/crunchytom/go-aws-auth"
"github.com/aldor007/go-aws-auth"
"encoding/xml"
"time"
)

var AutHeaderRegexpv4 = regexp.MustCompile("^(:?[A-Za-z0-9-]+) Credential=(:?.+),\\s*SignedHeaders=(:?[a-zA-Z0-9;-]+),\\s*Signature=(:?[a-zA-Z0-9]+)$")
var AuthHEaderRegexpv2 = regexp.MustCompile("^AWS ([A-Za-z0-9-]+):(.+)$")
var AuthHeaderRegexpv2 = regexp.MustCompile("^AWS ([A-Za-z0-9-]+):(.+)$")

func isAuthRequired(method string, auth string, path string) bool {
switch method {
case "GET", "HEAD", "OPTIONS":
if auth != "" {
return true
}
if path == "" {
return true
}
return false
case "POST", "PUT", "DELETE", "PATCH":
return true
}

return true
}

// BasicAuthWithConfig returns an BasicAuth middleware with config.
// See `BasicAuth()`.
func S3Middleware(config *config.Config) echo.MiddlewareFunc {
func S3AuthMiddleware(config *config.Config) echo.MiddlewareFunc {

return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
Expand All @@ -35,19 +54,11 @@ func S3Middleware(config *config.Config) echo.MiddlewareFunc {
// realPath = strings.Join(pathSlice[2:], "/")
//}

bucket, ok := config.Buckets[bucketName]

if !ok {
return echo.NewHTTPError(404, "unknown bucket")
}

// TODO: auth for get request


auth := req.Header.Get(echo.HeaderAuthorization)


if req.Method == "GET" && auth == "" {
if !isAuthRequired(req.Method, auth, path) {
return next(c)
}

Expand All @@ -63,6 +74,16 @@ func S3Middleware(config *config.Config) echo.MiddlewareFunc {
singedHeaders := strings.Split(matches[3], ";")
//signature := matches[4]
var credential awsauth.Credentials
bucket, ok := config.Buckets[bucketName]

if !ok {
buckets := config.BucketsByAccessKey(accessKey)
if len(buckets) == 0{
return echo.NewHTTPError(404, "unknown bucket")
}

bucket = buckets[0]
}

keys := bucket.Keys
for _, key := range keys {
Expand Down Expand Up @@ -103,6 +124,66 @@ func S3Middleware(config *config.Config) echo.MiddlewareFunc {

awsauth.Sign4ForRegion(validiatonReq, "mort", "s3", credential)
if auth == validiatonReq.Header.Get(echo.HeaderAuthorization) {
c.Set("accessKey", accessKey)
return next(c)
}

return echo.ErrForbidden
}

matches = AuthHeaderRegexpv2.FindStringSubmatch(auth)
if len(matches) == 3 {

accessKey := matches[1]
c.Set("accessKey", accessKey)
return next(c)
var credential awsauth.Credentials
bucket, ok := config.Buckets[bucketName]

if !ok {
buckets := config.BucketsByAccessKey(accessKey)
if len(buckets) == 0{
return echo.NewHTTPError(404, "unknown bucket")
}

bucket = buckets[0]
}

keys := bucket.Keys
for _, key := range keys {
if accessKey == key.AccessKey {
credential.AccessKeyID = accessKey
credential.SecretAccessKey = key.SecretAccessKey
break
}

}
if credential.AccessKeyID == "" {
return echo.ErrUnauthorized
}

validiatonReq, err := http.NewRequest(req.Method, req.URL.String(), req.Body)
if err != nil {
return echo.ErrUnauthorized
}
for h, v := range req.Header {
if strings.HasPrefix(strings.ToLower(h),"x-amz") {
validiatonReq.Header.Set(h, v[0])
}

switch h {
case "Content-Type", "Content-Md5", "Host":
validiatonReq.Header.Set(h, v[0])
}
}

validiatonReq.URL = req.URL
validiatonReq.Method = req.Method
validiatonReq.Body = req.Body
validiatonReq.Host = req.Host
awsauth.SignS3(validiatonReq, credential)
if auth == validiatonReq.Header.Get(echo.HeaderAuthorization) {
c.Set("accessKey", accessKey)
return next(c)
}

Expand All @@ -113,4 +194,50 @@ func S3Middleware(config *config.Config) echo.MiddlewareFunc {

}
}
}
}

type bucketXml struct {
XMLName xml.Name `xml:"Bucket"`
Name string `xml:"Name"`
CreationDate string `xml:"CreationDate"`

}

type listAllBucketsResult struct {
XMLName xml.Name `xml:"ListBucketsResult"`
Owner struct {
ID string `xml:"ID"`
DisplayName string `xml:"DisplayName"`
} `xml:"owner"`
Buckets []bucketXml `xml:"Buckets>Bucket"`
}


func S3Middleware(config *config.Config) echo.MiddlewareFunc {

return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
accessKey := c.Get("accessKey")
if accessKey == nil {
return next(c)
}

buckets := config.BucketsByAccessKey(accessKey.(string))
listAllBucketsXML := listAllBucketsResult{}
listAllBucketsXML.Owner.DisplayName = "test"
listAllBucketsXML.Owner.ID = "test"
//listAllBucketsXML.Buckets = make([]bucketXml, len(buckets))
for _, bucket := range buckets {
if bucket.Name != "" {
b := bucketXml{}
b.Name = bucket.Name
b.CreationDate = time.Now().Format(time.RFC3339)
listAllBucketsXML.Buckets = append(listAllBucketsXML.Buckets, b)
}
}

c.XML(200, listAllBucketsXML)
return nil
}
}
}

0 comments on commit 8deda1b

Please sign in to comment.