From 980d2292720061935176ee64dc5ef9c60f10db2f Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Tue, 17 Feb 2015 13:23:13 -0800 Subject: [PATCH] Add policy validation code more rigorous --- pkg/utils/config/config.go | 14 +++++ pkg/utils/policy/date.go | 2 +- pkg/utils/policy/policy.go | 108 ++++++++++++++++++++++++++++++++++++- 3 files changed, 121 insertions(+), 3 deletions(-) diff --git a/pkg/utils/config/config.go b/pkg/utils/config/config.go index fafa47489..a7851944e 100644 --- a/pkg/utils/config/config.go +++ b/pkg/utils/config/config.go @@ -144,3 +144,17 @@ func (c *Config) ReadConfig() error { c.Users = users return nil } + +func Loadusers() map[string]User { + c := Config{} + c.SetupConfig() + c.ReadConfig() + return c.Users +} + +func Loaduser(username string) User { + c := Config{} + c.SetupConfig() + c.ReadConfig() + return c.GetUser(username) +} diff --git a/pkg/utils/policy/date.go b/pkg/utils/policy/date.go index 2c1b83151..b22e8207a 100644 --- a/pkg/utils/policy/date.go +++ b/pkg/utils/policy/date.go @@ -24,7 +24,7 @@ func (d Date) IsZero() bool { // Convert string date in format YYYY-MM-DD to Date. // Leading and trailing spaces are ignored. If format is invalid returns zero. -func ParseDate(str string) (d Date, err error) { +func parseDate(str string) (d Date, err error) { str = strings.TrimSpace(str) if str == "0000-00-00" { return diff --git a/pkg/utils/policy/policy.go b/pkg/utils/policy/policy.go index ee3d10a15..9be426243 100644 --- a/pkg/utils/policy/policy.go +++ b/pkg/utils/policy/policy.go @@ -3,6 +3,7 @@ package policy import ( "encoding/json" "io" + "strings" ) type UserCred struct { @@ -15,6 +16,7 @@ type Stmt struct { Principal UserCred Action []string Resource []string + // TODO fix it in future if necessary - Condition {} } type BucketPolicy struct { @@ -22,7 +24,97 @@ type BucketPolicy struct { Statement []Stmt } -// TODO: Add more checks +const ( + awsResource = "arn:aws:s3:::" + minioResource = "minio:::" +) + +// TODO support canonical user +const ( + awsPrincipal = "arn:aws:iam::Account-ID:user/" + minioPrincipal = "minio::Account-ID:user/" +) + +var supportedActionMap = map[string]bool{ + "*": true, + "s3:GetObject": true, + "s3:ListBucket": true, + "s3:PutObject": true, + "s3:CreateBucket": true, + "s3:GetBucketPolicy": true, + "s3:DeleteBucketPolicy": true, + "s3:ListAllMyBuckets": true, + "s3:PutBucketPolicy": true, +} + +var supportedEffectMap = map[string]bool{ + "Allow": true, + "Deny": true, +} + +func isValidAction(action []string) bool { + var ok bool = false + for _, a := range action { + if supportedActionMap[a] { + ok = true + } + } + return ok +} + +func isValidEffect(effect string) bool { + if supportedEffectMap[effect] { + return true + } + return false +} + +func isValidResource(resources []string) bool { + var ok bool = false + for _, resource := range resources { + switch true { + case strings.HasPrefix(resource, awsResource): + bucket := strings.SplitAfter(resource, awsResource)[1] + ok = true + if len(bucket) == 0 { + ok = false + } + case strings.HasPrefix(resource, minioResource): + bucket := strings.SplitAfter(resource, minioResource)[1] + ok = true + if len(bucket) == 0 { + ok = false + } + default: + ok = false + } + } + return ok +} + +func isValidPrincipal(principal string) bool { + var ok bool = false + if principal == "*" { + return true + } + switch true { + case strings.HasPrefix(principal, awsPrincipal): + username := strings.SplitAfter(principal, awsPrincipal)[1] + ok = true + if len(username) == 0 { + ok = false + } + case strings.HasPrefix(principal, minioPrincipal): + username := strings.SplitAfter(principal, minioPrincipal)[1] + ok = true + if len(username) == 0 { + ok = false + } + default: + ok = false + } + return ok +} // validate request body is proper JSON func Parsepolicy(data io.Reader) (BucketPolicy, bool) { @@ -35,7 +127,7 @@ func Parsepolicy(data io.Reader) (BucketPolicy, bool) { if len(policy.Version) == 0 { goto error } - _, err = ParseDate(policy.Version) + _, err = parseDate(policy.Version) if err != nil { goto error } @@ -50,15 +142,27 @@ func Parsepolicy(data io.Reader) (BucketPolicy, bool) { if len(statement.Effect) == 0 { goto error } + if !isValidEffect(statement.Effect) { + goto error + } if len(statement.Principal.AWS) == 0 { goto error } + if !isValidPrincipal(statement.Principal.AWS) { + goto error + } if len(statement.Action) == 0 { goto error } + if !isValidAction(statement.Action) { + goto error + } if len(statement.Resource) == 0 { goto error } + if !isValidResource(statement.Resource) { + goto error + } } return policy, true