diff --git a/cmd/acl-handlers.go b/cmd/acl-handlers.go
index 69f327501..5c5810da2 100644
--- a/cmd/acl-handlers.go
+++ b/cmd/acl-handlers.go
@@ -25,7 +25,7 @@ import (
"github.com/gorilla/mux"
xhttp "github.com/minio/minio/cmd/http"
"github.com/minio/minio/cmd/logger"
- "github.com/minio/minio/pkg/bucket/policy"
+ "github.com/minio/pkg/bucket/policy"
)
// Data types used for returning dummy access control
diff --git a/cmd/admin-bucket-handlers.go b/cmd/admin-bucket-handlers.go
index 7ebe53b9c..e0f300a96 100644
--- a/cmd/admin-bucket-handlers.go
+++ b/cmd/admin-bucket-handlers.go
@@ -27,7 +27,7 @@ import (
jsoniter "github.com/json-iterator/go"
"github.com/minio/madmin-go"
"github.com/minio/minio/cmd/logger"
- iampolicy "github.com/minio/minio/pkg/iam/policy"
+ iampolicy "github.com/minio/pkg/iam/policy"
)
const (
diff --git a/cmd/admin-handlers-config-kv.go b/cmd/admin-handlers-config-kv.go
index 36af8753a..3d24373d0 100644
--- a/cmd/admin-handlers-config-kv.go
+++ b/cmd/admin-handlers-config-kv.go
@@ -37,7 +37,7 @@ import (
"github.com/minio/minio/cmd/config/storageclass"
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/auth"
- iampolicy "github.com/minio/minio/pkg/iam/policy"
+ iampolicy "github.com/minio/pkg/iam/policy"
)
func validateAdminReqConfigKV(ctx context.Context, w http.ResponseWriter, r *http.Request) (auth.Credentials, ObjectLayer) {
diff --git a/cmd/admin-handlers-users.go b/cmd/admin-handlers-users.go
index 0d615a72d..ee3b6a0a5 100644
--- a/cmd/admin-handlers-users.go
+++ b/cmd/admin-handlers-users.go
@@ -32,7 +32,7 @@ import (
"github.com/minio/minio/cmd/config/dns"
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/auth"
- iampolicy "github.com/minio/minio/pkg/iam/policy"
+ iampolicy "github.com/minio/pkg/iam/policy"
)
func validateAdminUsersReq(ctx context.Context, w http.ResponseWriter, r *http.Request, action iampolicy.AdminAction) (ObjectLayer, auth.Credentials) {
diff --git a/cmd/admin-handlers.go b/cmd/admin-handlers.go
index 3fd7038f4..93e16225e 100644
--- a/cmd/admin-handlers.go
+++ b/cmd/admin-handlers.go
@@ -46,9 +46,9 @@ import (
"github.com/minio/minio/pkg/auth"
"github.com/minio/minio/pkg/dsync"
"github.com/minio/minio/pkg/handlers"
- iampolicy "github.com/minio/minio/pkg/iam/policy"
"github.com/minio/minio/pkg/kms"
xnet "github.com/minio/minio/pkg/net"
+ iampolicy "github.com/minio/pkg/iam/policy"
)
const (
diff --git a/cmd/api-errors.go b/cmd/api-errors.go
index 57d839067..e47b2df3d 100644
--- a/cmd/api-errors.go
+++ b/cmd/api-errors.go
@@ -38,10 +38,10 @@ import (
"github.com/minio/minio/pkg/bucket/replication"
objectlock "github.com/minio/minio/pkg/bucket/object/lock"
- "github.com/minio/minio/pkg/bucket/policy"
"github.com/minio/minio/pkg/bucket/versioning"
"github.com/minio/minio/pkg/event"
"github.com/minio/minio/pkg/hash"
+ "github.com/minio/pkg/bucket/policy"
)
// APIError structure
diff --git a/cmd/auth-handler.go b/cmd/auth-handler.go
index e9721d79f..c311568fb 100644
--- a/cmd/auth-handler.go
+++ b/cmd/auth-handler.go
@@ -37,10 +37,10 @@ import (
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/auth"
objectlock "github.com/minio/minio/pkg/bucket/object/lock"
- "github.com/minio/minio/pkg/bucket/policy"
"github.com/minio/minio/pkg/etag"
"github.com/minio/minio/pkg/hash"
- iampolicy "github.com/minio/minio/pkg/iam/policy"
+ "github.com/minio/pkg/bucket/policy"
+ iampolicy "github.com/minio/pkg/iam/policy"
)
// Verify if request has JWT.
diff --git a/cmd/auth-handler_test.go b/cmd/auth-handler_test.go
index f8b3a917b..7fb7df765 100644
--- a/cmd/auth-handler_test.go
+++ b/cmd/auth-handler_test.go
@@ -29,7 +29,7 @@ import (
"time"
"github.com/minio/minio/pkg/auth"
- iampolicy "github.com/minio/minio/pkg/iam/policy"
+ iampolicy "github.com/minio/pkg/iam/policy"
)
// Test get request auth type.
diff --git a/cmd/bucket-encryption-handlers.go b/cmd/bucket-encryption-handlers.go
index 5f7fad500..c40a6ea64 100644
--- a/cmd/bucket-encryption-handlers.go
+++ b/cmd/bucket-encryption-handlers.go
@@ -25,7 +25,7 @@ import (
"github.com/gorilla/mux"
"github.com/minio/minio/cmd/logger"
- "github.com/minio/minio/pkg/bucket/policy"
+ "github.com/minio/pkg/bucket/policy"
)
const (
diff --git a/cmd/bucket-handlers.go b/cmd/bucket-handlers.go
index 2e19ee23e..3f6bc19b4 100644
--- a/cmd/bucket-handlers.go
+++ b/cmd/bucket-handlers.go
@@ -44,14 +44,14 @@ import (
xhttp "github.com/minio/minio/cmd/http"
"github.com/minio/minio/cmd/logger"
objectlock "github.com/minio/minio/pkg/bucket/object/lock"
- "github.com/minio/minio/pkg/bucket/policy"
"github.com/minio/minio/pkg/bucket/replication"
"github.com/minio/minio/pkg/event"
"github.com/minio/minio/pkg/handlers"
"github.com/minio/minio/pkg/hash"
- iampolicy "github.com/minio/minio/pkg/iam/policy"
"github.com/minio/minio/pkg/kms"
"github.com/minio/minio/pkg/sync/errgroup"
+ "github.com/minio/pkg/bucket/policy"
+ iampolicy "github.com/minio/pkg/iam/policy"
)
const (
diff --git a/cmd/bucket-lifecycle-handlers.go b/cmd/bucket-lifecycle-handlers.go
index 76888f357..84ca002a2 100644
--- a/cmd/bucket-lifecycle-handlers.go
+++ b/cmd/bucket-lifecycle-handlers.go
@@ -26,7 +26,7 @@ import (
xhttp "github.com/minio/minio/cmd/http"
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/bucket/lifecycle"
- "github.com/minio/minio/pkg/bucket/policy"
+ "github.com/minio/pkg/bucket/policy"
)
const (
diff --git a/cmd/bucket-listobjects-handlers.go b/cmd/bucket-listobjects-handlers.go
index f7b69bdff..08907721a 100644
--- a/cmd/bucket-listobjects-handlers.go
+++ b/cmd/bucket-listobjects-handlers.go
@@ -26,8 +26,8 @@ import (
"github.com/gorilla/mux"
"github.com/minio/minio/cmd/logger"
- "github.com/minio/minio/pkg/bucket/policy"
"github.com/minio/minio/pkg/sync/errgroup"
+ "github.com/minio/pkg/bucket/policy"
)
func concurrentDecryptETag(ctx context.Context, objects []ObjectInfo) {
diff --git a/cmd/bucket-metadata-sys.go b/cmd/bucket-metadata-sys.go
index dc5894bcf..dfaa8f9ec 100644
--- a/cmd/bucket-metadata-sys.go
+++ b/cmd/bucket-metadata-sys.go
@@ -30,12 +30,12 @@ import (
bucketsse "github.com/minio/minio/pkg/bucket/encryption"
"github.com/minio/minio/pkg/bucket/lifecycle"
objectlock "github.com/minio/minio/pkg/bucket/object/lock"
- "github.com/minio/minio/pkg/bucket/policy"
"github.com/minio/minio/pkg/bucket/replication"
"github.com/minio/minio/pkg/bucket/versioning"
"github.com/minio/minio/pkg/event"
"github.com/minio/minio/pkg/kms"
"github.com/minio/minio/pkg/sync/errgroup"
+ "github.com/minio/pkg/bucket/policy"
)
// BucketMetadataSys captures all bucket metadata for a given cluster.
diff --git a/cmd/bucket-metadata.go b/cmd/bucket-metadata.go
index d6b0cf95d..a69d38a32 100644
--- a/cmd/bucket-metadata.go
+++ b/cmd/bucket-metadata.go
@@ -36,12 +36,12 @@ import (
bucketsse "github.com/minio/minio/pkg/bucket/encryption"
"github.com/minio/minio/pkg/bucket/lifecycle"
objectlock "github.com/minio/minio/pkg/bucket/object/lock"
- "github.com/minio/minio/pkg/bucket/policy"
"github.com/minio/minio/pkg/bucket/replication"
"github.com/minio/minio/pkg/bucket/versioning"
"github.com/minio/minio/pkg/event"
"github.com/minio/minio/pkg/fips"
"github.com/minio/minio/pkg/kms"
+ "github.com/minio/pkg/bucket/policy"
"github.com/minio/sio"
)
diff --git a/cmd/bucket-notification-handlers.go b/cmd/bucket-notification-handlers.go
index e72703cf7..0af293dbe 100644
--- a/cmd/bucket-notification-handlers.go
+++ b/cmd/bucket-notification-handlers.go
@@ -25,8 +25,8 @@ import (
"github.com/gorilla/mux"
"github.com/minio/minio/cmd/logger"
- "github.com/minio/minio/pkg/bucket/policy"
"github.com/minio/minio/pkg/event"
+ "github.com/minio/pkg/bucket/policy"
)
const (
diff --git a/cmd/bucket-object-lock.go b/cmd/bucket-object-lock.go
index 0bac18aa5..4844f4c49 100644
--- a/cmd/bucket-object-lock.go
+++ b/cmd/bucket-object-lock.go
@@ -26,8 +26,8 @@ import (
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/auth"
objectlock "github.com/minio/minio/pkg/bucket/object/lock"
- "github.com/minio/minio/pkg/bucket/policy"
"github.com/minio/minio/pkg/bucket/replication"
+ "github.com/minio/pkg/bucket/policy"
)
// BucketObjectLockSys - map of bucket and retention configuration.
diff --git a/cmd/bucket-policy-handlers.go b/cmd/bucket-policy-handlers.go
index 20bc34d8b..a81feeb43 100644
--- a/cmd/bucket-policy-handlers.go
+++ b/cmd/bucket-policy-handlers.go
@@ -25,7 +25,7 @@ import (
humanize "github.com/dustin/go-humanize"
"github.com/gorilla/mux"
"github.com/minio/minio/cmd/logger"
- "github.com/minio/minio/pkg/bucket/policy"
+ "github.com/minio/pkg/bucket/policy"
)
const (
diff --git a/cmd/bucket-policy-handlers_test.go b/cmd/bucket-policy-handlers_test.go
index 7716477a7..7470b7d00 100644
--- a/cmd/bucket-policy-handlers_test.go
+++ b/cmd/bucket-policy-handlers_test.go
@@ -29,8 +29,8 @@ import (
"testing"
"github.com/minio/minio/pkg/auth"
- "github.com/minio/minio/pkg/bucket/policy"
- "github.com/minio/minio/pkg/bucket/policy/condition"
+ "github.com/minio/pkg/bucket/policy"
+ "github.com/minio/pkg/bucket/policy/condition"
)
func getAnonReadOnlyBucketPolicy(bucketName string) *policy.Policy {
diff --git a/cmd/bucket-policy.go b/cmd/bucket-policy.go
index dcc8c87e7..b94c7ba0f 100644
--- a/cmd/bucket-policy.go
+++ b/cmd/bucket-policy.go
@@ -29,8 +29,8 @@ import (
miniogopolicy "github.com/minio/minio-go/v7/pkg/policy"
xhttp "github.com/minio/minio/cmd/http"
"github.com/minio/minio/cmd/logger"
- "github.com/minio/minio/pkg/bucket/policy"
"github.com/minio/minio/pkg/handlers"
+ "github.com/minio/pkg/bucket/policy"
)
// PolicySys - policy subsystem.
diff --git a/cmd/bucket-replication.go b/cmd/bucket-replication.go
index b0f308a2c..b9363ca1d 100644
--- a/cmd/bucket-replication.go
+++ b/cmd/bucket-replication.go
@@ -38,7 +38,7 @@ import (
"github.com/minio/minio/pkg/bucket/bandwidth"
"github.com/minio/minio/pkg/bucket/replication"
"github.com/minio/minio/pkg/event"
- iampolicy "github.com/minio/minio/pkg/iam/policy"
+ iampolicy "github.com/minio/pkg/iam/policy"
)
// gets replication config associated to a given bucket name.
diff --git a/cmd/bucket-versioning-handler.go b/cmd/bucket-versioning-handler.go
index c1ca8e449..60b919c90 100644
--- a/cmd/bucket-versioning-handler.go
+++ b/cmd/bucket-versioning-handler.go
@@ -25,8 +25,8 @@ import (
humanize "github.com/dustin/go-humanize"
"github.com/gorilla/mux"
"github.com/minio/minio/cmd/logger"
- "github.com/minio/minio/pkg/bucket/policy"
"github.com/minio/minio/pkg/bucket/versioning"
+ "github.com/minio/pkg/bucket/policy"
)
const (
diff --git a/cmd/config/identity/openid/jwt.go b/cmd/config/identity/openid/jwt.go
index 03773e3f6..64aaa72b4 100644
--- a/cmd/config/identity/openid/jwt.go
+++ b/cmd/config/identity/openid/jwt.go
@@ -32,9 +32,9 @@ import (
jwtgo "github.com/dgrijalva/jwt-go"
"github.com/minio/minio/cmd/config"
"github.com/minio/minio/pkg/auth"
- iampolicy "github.com/minio/minio/pkg/iam/policy"
xnet "github.com/minio/minio/pkg/net"
"github.com/minio/pkg/env"
+ iampolicy "github.com/minio/pkg/iam/policy"
)
// Config - OpenID Config
diff --git a/cmd/config/policy/opa/config.go b/cmd/config/policy/opa/config.go
index cf478a161..8b86847ca 100644
--- a/cmd/config/policy/opa/config.go
+++ b/cmd/config/policy/opa/config.go
@@ -25,9 +25,9 @@ import (
"net/http"
"github.com/minio/minio/cmd/config"
- iampolicy "github.com/minio/minio/pkg/iam/policy"
xnet "github.com/minio/minio/pkg/net"
"github.com/minio/pkg/env"
+ iampolicy "github.com/minio/pkg/iam/policy"
)
// Env IAM OPA URL
diff --git a/cmd/dummy-handlers.go b/cmd/dummy-handlers.go
index 4b30ce22e..d0d2828d5 100644
--- a/cmd/dummy-handlers.go
+++ b/cmd/dummy-handlers.go
@@ -22,7 +22,7 @@ import (
"github.com/gorilla/mux"
"github.com/minio/minio/cmd/logger"
- "github.com/minio/minio/pkg/bucket/policy"
+ "github.com/minio/pkg/bucket/policy"
)
// Data types used for returning dummy tagging XML.
diff --git a/cmd/fs-v1.go b/cmd/fs-v1.go
index 91f374e49..5ebe26722 100644
--- a/cmd/fs-v1.go
+++ b/cmd/fs-v1.go
@@ -40,11 +40,11 @@ import (
"github.com/minio/minio/cmd/config"
xhttp "github.com/minio/minio/cmd/http"
"github.com/minio/minio/cmd/logger"
- "github.com/minio/minio/pkg/bucket/policy"
"github.com/minio/minio/pkg/color"
xioutil "github.com/minio/minio/pkg/ioutil"
"github.com/minio/minio/pkg/lock"
"github.com/minio/minio/pkg/mountinfo"
+ "github.com/minio/pkg/bucket/policy"
"github.com/minio/pkg/mimedb"
)
diff --git a/cmd/gateway-unsupported.go b/cmd/gateway-unsupported.go
index bc2d57b83..e9b4f6956 100644
--- a/cmd/gateway-unsupported.go
+++ b/cmd/gateway-unsupported.go
@@ -26,8 +26,8 @@ import (
"github.com/minio/minio-go/v7/pkg/tags"
bucketsse "github.com/minio/minio/pkg/bucket/encryption"
"github.com/minio/minio/pkg/bucket/lifecycle"
- "github.com/minio/minio/pkg/bucket/policy"
"github.com/minio/minio/pkg/bucket/versioning"
+ "github.com/minio/pkg/bucket/policy"
"github.com/minio/madmin-go"
)
diff --git a/cmd/gateway/azure/gateway-azure.go b/cmd/gateway/azure/gateway-azure.go
index 3901aa85c..9d612e5e1 100644
--- a/cmd/gateway/azure/gateway-azure.go
+++ b/cmd/gateway/azure/gateway-azure.go
@@ -45,8 +45,8 @@ import (
minio "github.com/minio/minio/cmd"
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/auth"
- "github.com/minio/minio/pkg/bucket/policy"
- "github.com/minio/minio/pkg/bucket/policy/condition"
+ "github.com/minio/pkg/bucket/policy"
+ "github.com/minio/pkg/bucket/policy/condition"
"github.com/minio/pkg/env"
)
diff --git a/cmd/gateway/gcs/gateway-gcs.go b/cmd/gateway/gcs/gateway-gcs.go
index 724af2750..1aa5f34f4 100644
--- a/cmd/gateway/gcs/gateway-gcs.go
+++ b/cmd/gateway/gcs/gateway-gcs.go
@@ -42,8 +42,8 @@ import (
minio "github.com/minio/minio/cmd"
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/auth"
- "github.com/minio/minio/pkg/bucket/policy"
- "github.com/minio/minio/pkg/bucket/policy/condition"
+ "github.com/minio/pkg/bucket/policy"
+ "github.com/minio/pkg/bucket/policy/condition"
"github.com/minio/pkg/env"
"google.golang.org/api/googleapi"
"google.golang.org/api/iterator"
diff --git a/cmd/gateway/s3/gateway-s3.go b/cmd/gateway/s3/gateway-s3.go
index e076e32d4..51266b6b4 100644
--- a/cmd/gateway/s3/gateway-s3.go
+++ b/cmd/gateway/s3/gateway-s3.go
@@ -37,7 +37,7 @@ import (
xhttp "github.com/minio/minio/cmd/http"
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/auth"
- "github.com/minio/minio/pkg/bucket/policy"
+ "github.com/minio/pkg/bucket/policy"
)
func init() {
diff --git a/cmd/iam-etcd-store.go b/cmd/iam-etcd-store.go
index 97b38b2a8..f6a77470a 100644
--- a/cmd/iam-etcd-store.go
+++ b/cmd/iam-etcd-store.go
@@ -33,8 +33,8 @@ import (
"github.com/minio/minio/cmd/config"
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/auth"
- iampolicy "github.com/minio/minio/pkg/iam/policy"
"github.com/minio/minio/pkg/kms"
+ iampolicy "github.com/minio/pkg/iam/policy"
"go.etcd.io/etcd/api/v3/mvccpb"
etcd "go.etcd.io/etcd/client/v3"
)
diff --git a/cmd/iam-object-store.go b/cmd/iam-object-store.go
index 00152b46a..d01be1e19 100644
--- a/cmd/iam-object-store.go
+++ b/cmd/iam-object-store.go
@@ -29,8 +29,8 @@ import (
"github.com/minio/minio/cmd/config"
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/auth"
- iampolicy "github.com/minio/minio/pkg/iam/policy"
"github.com/minio/minio/pkg/kms"
+ iampolicy "github.com/minio/pkg/iam/policy"
)
// IAMObjectStore implements IAMStorageAPI
diff --git a/cmd/iam.go b/cmd/iam.go
index b427e1578..ba2e15799 100644
--- a/cmd/iam.go
+++ b/cmd/iam.go
@@ -34,7 +34,7 @@ import (
"github.com/minio/minio-go/v7/pkg/set"
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/auth"
- iampolicy "github.com/minio/minio/pkg/iam/policy"
+ iampolicy "github.com/minio/pkg/iam/policy"
)
// UsersSysType - defines the type of users and groups system that is
diff --git a/cmd/listen-notification-handlers.go b/cmd/listen-notification-handlers.go
index ce46a8eee..a262d8d9d 100644
--- a/cmd/listen-notification-handlers.go
+++ b/cmd/listen-notification-handlers.go
@@ -24,8 +24,8 @@ import (
"github.com/gorilla/mux"
"github.com/minio/minio/cmd/logger"
- policy "github.com/minio/minio/pkg/bucket/policy"
"github.com/minio/minio/pkg/event"
+ policy "github.com/minio/pkg/bucket/policy"
)
func (api objectAPIHandlers) ListenNotificationHandler(w http.ResponseWriter, r *http.Request) {
diff --git a/cmd/metrics.go b/cmd/metrics.go
index d3850420b..fdbb12b08 100644
--- a/cmd/metrics.go
+++ b/cmd/metrics.go
@@ -25,7 +25,7 @@ import (
"github.com/minio/madmin-go"
"github.com/minio/minio/cmd/logger"
- iampolicy "github.com/minio/minio/pkg/iam/policy"
+ iampolicy "github.com/minio/pkg/iam/policy"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
diff --git a/cmd/notification.go b/cmd/notification.go
index 9f371201b..d09c9c82b 100644
--- a/cmd/notification.go
+++ b/cmd/notification.go
@@ -40,10 +40,10 @@ import (
xhttp "github.com/minio/minio/cmd/http"
"github.com/minio/minio/cmd/logger"
bucketBandwidth "github.com/minio/minio/pkg/bucket/bandwidth"
- "github.com/minio/minio/pkg/bucket/policy"
"github.com/minio/minio/pkg/event"
xnet "github.com/minio/minio/pkg/net"
"github.com/minio/minio/pkg/sync/errgroup"
+ "github.com/minio/pkg/bucket/policy"
)
// NotificationSys - notification system.
diff --git a/cmd/object-api-interface.go b/cmd/object-api-interface.go
index 18cdc622c..44ef1d323 100644
--- a/cmd/object-api-interface.go
+++ b/cmd/object-api-interface.go
@@ -26,7 +26,7 @@ import (
"github.com/minio/madmin-go"
"github.com/minio/minio-go/v7/pkg/encrypt"
"github.com/minio/minio-go/v7/pkg/tags"
- "github.com/minio/minio/pkg/bucket/policy"
+ "github.com/minio/pkg/bucket/policy"
)
// CheckPreconditionFn returns true if precondition check failed.
diff --git a/cmd/object-handlers.go b/cmd/object-handlers.go
index 775a9f104..e3611cf48 100644
--- a/cmd/object-handlers.go
+++ b/cmd/object-handlers.go
@@ -47,18 +47,18 @@ import (
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/bucket/lifecycle"
objectlock "github.com/minio/minio/pkg/bucket/object/lock"
- "github.com/minio/minio/pkg/bucket/policy"
"github.com/minio/minio/pkg/bucket/replication"
"github.com/minio/minio/pkg/etag"
"github.com/minio/minio/pkg/event"
"github.com/minio/minio/pkg/fips"
"github.com/minio/minio/pkg/handlers"
"github.com/minio/minio/pkg/hash"
- iampolicy "github.com/minio/minio/pkg/iam/policy"
"github.com/minio/minio/pkg/ioutil"
"github.com/minio/minio/pkg/kms"
xnet "github.com/minio/minio/pkg/net"
"github.com/minio/minio/pkg/s3select"
+ "github.com/minio/pkg/bucket/policy"
+ iampolicy "github.com/minio/pkg/iam/policy"
"github.com/minio/sio"
)
diff --git a/cmd/policy_test.go b/cmd/policy_test.go
index c8157538a..fae883976 100644
--- a/cmd/policy_test.go
+++ b/cmd/policy_test.go
@@ -23,8 +23,8 @@ import (
miniogopolicy "github.com/minio/minio-go/v7/pkg/policy"
"github.com/minio/minio-go/v7/pkg/set"
- "github.com/minio/minio/pkg/bucket/policy"
- "github.com/minio/minio/pkg/bucket/policy/condition"
+ "github.com/minio/pkg/bucket/policy"
+ "github.com/minio/pkg/bucket/policy/condition"
)
func TestPolicySysIsAllowed(t *testing.T) {
diff --git a/cmd/server_test.go b/cmd/server_test.go
index a72852faa..e8eeaf752 100644
--- a/cmd/server_test.go
+++ b/cmd/server_test.go
@@ -35,7 +35,7 @@ import (
humanize "github.com/dustin/go-humanize"
"github.com/minio/minio-go/v7/pkg/set"
xhttp "github.com/minio/minio/cmd/http"
- "github.com/minio/minio/pkg/bucket/policy"
+ "github.com/minio/pkg/bucket/policy"
)
// API suite container common to both FS and Erasure.
diff --git a/cmd/sts-handlers.go b/cmd/sts-handlers.go
index bb11c172f..323ab508e 100644
--- a/cmd/sts-handlers.go
+++ b/cmd/sts-handlers.go
@@ -31,7 +31,7 @@ import (
xhttp "github.com/minio/minio/cmd/http"
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/auth"
- iampolicy "github.com/minio/minio/pkg/iam/policy"
+ iampolicy "github.com/minio/pkg/iam/policy"
"github.com/minio/pkg/wildcard"
)
diff --git a/cmd/test-utils_test.go b/cmd/test-utils_test.go
index 5d9ce13d0..5a3b48965 100644
--- a/cmd/test-utils_test.go
+++ b/cmd/test-utils_test.go
@@ -65,8 +65,8 @@ import (
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/cmd/rest"
"github.com/minio/minio/pkg/auth"
- "github.com/minio/minio/pkg/bucket/policy"
"github.com/minio/minio/pkg/hash"
+ "github.com/minio/pkg/bucket/policy"
)
// TestMain to set up global env.
diff --git a/cmd/tier-handlers.go b/cmd/tier-handlers.go
index 7a5289b2f..17c9aba54 100644
--- a/cmd/tier-handlers.go
+++ b/cmd/tier-handlers.go
@@ -26,7 +26,7 @@ import (
jsoniter "github.com/json-iterator/go"
"github.com/minio/madmin-go"
"github.com/minio/minio/cmd/logger"
- iampolicy "github.com/minio/minio/pkg/iam/policy"
+ iampolicy "github.com/minio/pkg/iam/policy"
)
var (
diff --git a/cmd/web-handlers.go b/cmd/web-handlers.go
index 76853f169..7868b125b 100644
--- a/cmd/web-handlers.go
+++ b/cmd/web-handlers.go
@@ -48,14 +48,14 @@ import (
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/auth"
objectlock "github.com/minio/minio/pkg/bucket/object/lock"
- "github.com/minio/minio/pkg/bucket/policy"
"github.com/minio/minio/pkg/bucket/replication"
"github.com/minio/minio/pkg/etag"
"github.com/minio/minio/pkg/event"
"github.com/minio/minio/pkg/handlers"
"github.com/minio/minio/pkg/hash"
- iampolicy "github.com/minio/minio/pkg/iam/policy"
"github.com/minio/minio/pkg/ioutil"
+ "github.com/minio/pkg/bucket/policy"
+ iampolicy "github.com/minio/pkg/iam/policy"
"github.com/minio/rpc/json2"
)
diff --git a/go.mod b/go.mod
index d06e4f257..c7d46e762 100644
--- a/go.mod
+++ b/go.mod
@@ -47,7 +47,7 @@ require (
github.com/minio/madmin-go v1.0.2
github.com/minio/minio-go/v7 v7.0.11-0.20210302210017-6ae69c73ce78
github.com/minio/parquet-go v1.0.0
- github.com/minio/pkg v1.0.2
+ github.com/minio/pkg v1.0.3
github.com/minio/rpc v1.0.0
github.com/minio/selfupdate v0.3.1
github.com/minio/sha256-simd v1.0.0
diff --git a/go.sum b/go.sum
index a4f1c7f70..2f2a19860 100644
--- a/go.sum
+++ b/go.sum
@@ -504,8 +504,8 @@ github.com/minio/minio-go/v7 v7.0.11-0.20210302210017-6ae69c73ce78 h1:v7OMbUnWky
github.com/minio/minio-go/v7 v7.0.11-0.20210302210017-6ae69c73ce78/go.mod h1:mTh2uJuAbEqdhMVl6CMIIZLUeiMiWtJR4JB8/5g2skw=
github.com/minio/parquet-go v1.0.0 h1:fcWsEvub04Nsl/4hiRBDWlbqd6jhacQieV07a+nhiIk=
github.com/minio/parquet-go v1.0.0/go.mod h1:aQlkSOfOq2AtQKkuou3mosNVMwNokd+faTacxxk/oHA=
-github.com/minio/pkg v1.0.2 h1:vUlNMJbOgP/Hi/ekN+tl1xTOm3Q39gPr5XurDVOgvBA=
-github.com/minio/pkg v1.0.2/go.mod h1:e9WOU0bav8jd8AzloFjCTSiXSNqnXqxbzGwlH+2rQnI=
+github.com/minio/pkg v1.0.3 h1:tUhM6lG/BdNB0+5f2RbE4ifCAYwMs6cRJnZ/AY0WIeQ=
+github.com/minio/pkg v1.0.3/go.mod h1:obU54TZ9QlMv0TRaDgQ/JTzf11ZSXxnSfLrm4tMtBP8=
github.com/minio/rpc v1.0.0 h1:tJCHyLfQF6k6HlMQFpKy2FO/7lc2WP8gLDGMZp18E70=
github.com/minio/rpc v1.0.0/go.mod h1:b9xqF7J0xeMXr0cM4pnBlP7Te7PDsG5JrRxl5dG6Ldk=
github.com/minio/selfupdate v0.3.1 h1:BWEFSNnrZVMUWXbXIgLDNDjbejkmpAmZvy/nCz1HlEs=
diff --git a/pkg/bucket/policy/action.go b/pkg/bucket/policy/action.go
deleted file mode 100644
index 94ab27a94..000000000
--- a/pkg/bucket/policy/action.go
+++ /dev/null
@@ -1,426 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package policy
-
-import (
- "encoding/json"
-
- "github.com/minio/minio/pkg/bucket/policy/condition"
-)
-
-// Action - policy action.
-// Refer https://docs.aws.amazon.com/IAM/latest/UserGuide/list_amazons3.html
-// for more information about available actions.
-type Action string
-
-const (
- // AbortMultipartUploadAction - AbortMultipartUpload Rest API action.
- AbortMultipartUploadAction Action = "s3:AbortMultipartUpload"
-
- // CreateBucketAction - CreateBucket Rest API action.
- CreateBucketAction = "s3:CreateBucket"
-
- // DeleteBucketAction - DeleteBucket Rest API action.
- DeleteBucketAction = "s3:DeleteBucket"
-
- // ForceDeleteBucketAction - DeleteBucket Rest API action when x-minio-force-delete flag
- // is specified.
- ForceDeleteBucketAction = "s3:ForceDeleteBucket"
-
- // DeleteBucketPolicyAction - DeleteBucketPolicy Rest API action.
- DeleteBucketPolicyAction = "s3:DeleteBucketPolicy"
-
- // DeleteObjectAction - DeleteObject Rest API action.
- DeleteObjectAction = "s3:DeleteObject"
-
- // GetBucketLocationAction - GetBucketLocation Rest API action.
- GetBucketLocationAction = "s3:GetBucketLocation"
-
- // GetBucketNotificationAction - GetBucketNotification Rest API action.
- GetBucketNotificationAction = "s3:GetBucketNotification"
-
- // GetBucketPolicyAction - GetBucketPolicy Rest API action.
- GetBucketPolicyAction = "s3:GetBucketPolicy"
-
- // GetObjectAction - GetObject Rest API action.
- GetObjectAction = "s3:GetObject"
-
- // HeadBucketAction - HeadBucket Rest API action. This action is unused in minio.
- HeadBucketAction = "s3:HeadBucket"
-
- // ListAllMyBucketsAction - ListAllMyBuckets (List buckets) Rest API action.
- ListAllMyBucketsAction = "s3:ListAllMyBuckets"
-
- // ListBucketAction - ListBucket Rest API action.
- ListBucketAction = "s3:ListBucket"
-
- // GetBucketPolicyStatusAction - Retrieves the policy status for a bucket.
- GetBucketPolicyStatusAction = "s3:GetBucketPolicyStatus"
-
- // ListBucketMultipartUploadsAction - ListMultipartUploads Rest API action.
- ListBucketMultipartUploadsAction = "s3:ListBucketMultipartUploads"
-
- // ListBucketVersionsAction - ListBucket versions Rest API action.
- ListBucketVersionsAction = "s3:ListBucketVersions"
-
- // ListenNotificationAction - ListenNotification Rest API action.
- // This is MinIO extension.
- ListenNotificationAction = "s3:ListenNotification"
-
- // ListenBucketNotificationAction - ListenBucketNotification Rest API action.
- // This is MinIO extension.
- ListenBucketNotificationAction = "s3:ListenBucketNotification"
-
- // ListMultipartUploadPartsAction - ListParts Rest API action.
- ListMultipartUploadPartsAction = "s3:ListMultipartUploadParts"
-
- // PutBucketNotificationAction - PutObjectNotification Rest API action.
- PutBucketNotificationAction = "s3:PutBucketNotification"
-
- // PutBucketPolicyAction - PutBucketPolicy Rest API action.
- PutBucketPolicyAction = "s3:PutBucketPolicy"
-
- // PutObjectAction - PutObject Rest API action.
- PutObjectAction = "s3:PutObject"
-
- // PutBucketLifecycleAction - PutBucketLifecycle Rest API action.
- PutBucketLifecycleAction = "s3:PutLifecycleConfiguration"
-
- // GetBucketLifecycleAction - GetBucketLifecycle Rest API action.
- GetBucketLifecycleAction = "s3:GetLifecycleConfiguration"
-
- // BypassGovernanceRetentionAction - bypass governance retention for PutObjectRetention, PutObject and DeleteObject Rest API action.
- BypassGovernanceRetentionAction = "s3:BypassGovernanceRetention"
- // PutObjectRetentionAction - PutObjectRetention Rest API action.
- PutObjectRetentionAction = "s3:PutObjectRetention"
-
- // GetObjectRetentionAction - GetObjectRetention, GetObject, HeadObject Rest API action.
- GetObjectRetentionAction = "s3:GetObjectRetention"
- // GetObjectLegalHoldAction - GetObjectLegalHold, GetObject Rest API action.
- GetObjectLegalHoldAction = "s3:GetObjectLegalHold"
- // PutObjectLegalHoldAction - PutObjectLegalHold, PutObject Rest API action.
- PutObjectLegalHoldAction = "s3:PutObjectLegalHold"
- // GetBucketObjectLockConfigurationAction - GetObjectLockConfiguration Rest API action
- GetBucketObjectLockConfigurationAction = "s3:GetBucketObjectLockConfiguration"
- // PutBucketObjectLockConfigurationAction - PutObjectLockConfiguration Rest API action
- PutBucketObjectLockConfigurationAction = "s3:PutBucketObjectLockConfiguration"
-
- // GetBucketTaggingAction - GetTagging Rest API action
- GetBucketTaggingAction = "s3:GetBucketTagging"
- // PutBucketTaggingAction - PutTagging Rest API action
- PutBucketTaggingAction = "s3:PutBucketTagging"
-
- // GetObjectTaggingAction - Get Object Tags API action
- GetObjectTaggingAction = "s3:GetObjectTagging"
- // PutObjectTaggingAction - Put Object Tags API action
- PutObjectTaggingAction = "s3:PutObjectTagging"
- // DeleteObjectTaggingAction - Delete Object Tags API action
- DeleteObjectTaggingAction = "s3:DeleteObjectTagging"
-
- // PutBucketEncryptionAction - PutBucketEncryption REST API action
- PutBucketEncryptionAction = "s3:PutEncryptionConfiguration"
- // GetBucketEncryptionAction - GetBucketEncryption REST API action
- GetBucketEncryptionAction = "s3:GetEncryptionConfiguration"
-
- // PutBucketVersioningAction - PutBucketVersioning REST API action
- PutBucketVersioningAction = "s3:PutBucketVersioning"
- // GetBucketVersioningAction - GetBucketVersioning REST API action
- GetBucketVersioningAction = "s3:GetBucketVersioning"
-
- // DeleteObjectVersionAction - DeleteObjectVersion Rest API action.
- DeleteObjectVersionAction = "s3:DeleteObjectVersion"
-
- // DeleteObjectVersionTaggingAction - DeleteObjectVersionTagging Rest API action.
- DeleteObjectVersionTaggingAction = "s3:DeleteObjectVersionTagging"
-
- // GetObjectVersionAction - GetObjectVersionAction Rest API action.
- GetObjectVersionAction = "s3:GetObjectVersion"
-
- // GetObjectVersionTaggingAction - GetObjectVersionTagging Rest API action.
- GetObjectVersionTaggingAction = "s3:GetObjectVersionTagging"
-
- // PutObjectVersionTaggingAction - PutObjectVersionTagging Rest API action.
- PutObjectVersionTaggingAction = "s3:PutObjectVersionTagging"
-
- // GetReplicationConfigurationAction - GetReplicationConfiguration REST API action
- GetReplicationConfigurationAction = "s3:GetReplicationConfiguration"
- // PutReplicationConfigurationAction - PutReplicationConfiguration REST API action
- PutReplicationConfigurationAction = "s3:PutReplicationConfiguration"
-
- // ReplicateObjectAction - ReplicateObject REST API action
- ReplicateObjectAction = "s3:ReplicateObject"
-
- // ReplicateDeleteAction - ReplicateDelete REST API action
- ReplicateDeleteAction = "s3:ReplicateDelete"
-
- // ReplicateTagsAction - ReplicateTags REST API action
- ReplicateTagsAction = "s3:ReplicateTags"
-
- // GetObjectVersionForReplicationAction - GetObjectVersionForReplication REST API action
- GetObjectVersionForReplicationAction = "s3:GetObjectVersionForReplication"
-
- // RestoreObjectAction - RestoreObject REST API action
- RestoreObjectAction = "s3:RestoreObject"
-)
-
-// List of all supported object actions.
-var supportedObjectActions = map[Action]struct{}{
- AbortMultipartUploadAction: {},
- DeleteObjectAction: {},
- GetObjectAction: {},
- ListMultipartUploadPartsAction: {},
- PutObjectAction: {},
- BypassGovernanceRetentionAction: {},
- PutObjectRetentionAction: {},
- GetObjectRetentionAction: {},
- PutObjectLegalHoldAction: {},
- GetObjectLegalHoldAction: {},
- GetObjectTaggingAction: {},
- PutObjectTaggingAction: {},
- DeleteObjectTaggingAction: {},
- GetObjectVersionAction: {},
- GetObjectVersionTaggingAction: {},
- DeleteObjectVersionAction: {},
- DeleteObjectVersionTaggingAction: {},
- PutObjectVersionTaggingAction: {},
- ReplicateObjectAction: {},
- ReplicateDeleteAction: {},
- ReplicateTagsAction: {},
- GetObjectVersionForReplicationAction: {},
- RestoreObjectAction: {},
-}
-
-// isObjectAction - returns whether action is object type or not.
-func (action Action) isObjectAction() bool {
- _, ok := supportedObjectActions[action]
- return ok
-}
-
-// List of all supported actions.
-var supportedActions = map[Action]struct{}{
- AbortMultipartUploadAction: {},
- CreateBucketAction: {},
- DeleteBucketAction: {},
- ForceDeleteBucketAction: {},
- DeleteBucketPolicyAction: {},
- DeleteObjectAction: {},
- GetBucketLocationAction: {},
- GetBucketNotificationAction: {},
- GetBucketPolicyAction: {},
- GetObjectAction: {},
- HeadBucketAction: {},
- ListAllMyBucketsAction: {},
- ListBucketAction: {},
- GetBucketPolicyStatusAction: {},
- ListBucketVersionsAction: {},
- ListBucketMultipartUploadsAction: {},
- ListenNotificationAction: {},
- ListenBucketNotificationAction: {},
- ListMultipartUploadPartsAction: {},
- PutBucketNotificationAction: {},
- PutBucketPolicyAction: {},
- PutObjectAction: {},
- GetBucketLifecycleAction: {},
- PutBucketLifecycleAction: {},
- PutObjectRetentionAction: {},
- GetObjectRetentionAction: {},
- GetObjectLegalHoldAction: {},
- PutObjectLegalHoldAction: {},
- PutBucketObjectLockConfigurationAction: {},
- GetBucketObjectLockConfigurationAction: {},
- PutBucketTaggingAction: {},
- GetBucketTaggingAction: {},
- GetObjectVersionAction: {},
- GetObjectVersionTaggingAction: {},
- DeleteObjectVersionAction: {},
- DeleteObjectVersionTaggingAction: {},
- PutObjectVersionTaggingAction: {},
- BypassGovernanceRetentionAction: {},
- GetObjectTaggingAction: {},
- PutObjectTaggingAction: {},
- DeleteObjectTaggingAction: {},
- PutBucketEncryptionAction: {},
- GetBucketEncryptionAction: {},
- PutBucketVersioningAction: {},
- GetBucketVersioningAction: {},
- GetReplicationConfigurationAction: {},
- PutReplicationConfigurationAction: {},
- ReplicateObjectAction: {},
- ReplicateDeleteAction: {},
- ReplicateTagsAction: {},
- GetObjectVersionForReplicationAction: {},
- RestoreObjectAction: {},
-}
-
-// IsValid - checks if action is valid or not.
-func (action Action) IsValid() bool {
- _, ok := supportedActions[action]
- return ok
-}
-
-// MarshalJSON - encodes Action to JSON data.
-func (action Action) MarshalJSON() ([]byte, error) {
- if action.IsValid() {
- return json.Marshal(string(action))
- }
-
- return nil, Errorf("invalid action '%v'", action)
-}
-
-// UnmarshalJSON - decodes JSON data to Action.
-func (action *Action) UnmarshalJSON(data []byte) error {
- var s string
-
- if err := json.Unmarshal(data, &s); err != nil {
- return err
- }
-
- a := Action(s)
- if !a.IsValid() {
- return Errorf("invalid action '%v'", s)
- }
-
- *action = a
-
- return nil
-}
-
-func parseAction(s string) (Action, error) {
- action := Action(s)
-
- if action.IsValid() {
- return action, nil
- }
-
- return action, Errorf("unsupported action '%v'", s)
-}
-
-// actionConditionKeyMap - holds mapping of supported condition key for an action.
-var actionConditionKeyMap = map[Action]condition.KeySet{
- AbortMultipartUploadAction: condition.NewKeySet(condition.CommonKeys...),
-
- CreateBucketAction: condition.NewKeySet(condition.CommonKeys...),
-
- DeleteObjectAction: condition.NewKeySet(condition.CommonKeys...),
-
- GetBucketLocationAction: condition.NewKeySet(condition.CommonKeys...),
-
- GetBucketPolicyStatusAction: condition.NewKeySet(condition.CommonKeys...),
-
- GetObjectAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3XAmzServerSideEncryption,
- condition.S3XAmzServerSideEncryptionCustomerAlgorithm,
- }, condition.CommonKeys...)...),
-
- HeadBucketAction: condition.NewKeySet(condition.CommonKeys...),
-
- ListAllMyBucketsAction: condition.NewKeySet(condition.CommonKeys...),
-
- ListBucketAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3Prefix,
- condition.S3Delimiter,
- condition.S3MaxKeys,
- }, condition.CommonKeys...)...),
-
- ListBucketVersionsAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3Prefix,
- condition.S3Delimiter,
- condition.S3MaxKeys,
- }, condition.CommonKeys...)...),
-
- ListBucketMultipartUploadsAction: condition.NewKeySet(condition.CommonKeys...),
-
- ListenNotificationAction: condition.NewKeySet(condition.CommonKeys...),
-
- ListenBucketNotificationAction: condition.NewKeySet(condition.CommonKeys...),
-
- ListMultipartUploadPartsAction: condition.NewKeySet(condition.CommonKeys...),
-
- PutObjectAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3XAmzCopySource,
- condition.S3XAmzServerSideEncryption,
- condition.S3XAmzServerSideEncryptionCustomerAlgorithm,
- condition.S3XAmzMetadataDirective,
- condition.S3XAmzStorageClass,
- condition.S3ObjectLockRetainUntilDate,
- condition.S3ObjectLockMode,
- condition.S3ObjectLockLegalHold,
- }, condition.CommonKeys...)...),
-
- // https://docs.aws.amazon.com/AmazonS3/latest/dev/list_amazons3.html
- // LockLegalHold is not supported with PutObjectRetentionAction
- PutObjectRetentionAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3ObjectLockRemainingRetentionDays,
- condition.S3ObjectLockRetainUntilDate,
- condition.S3ObjectLockMode,
- }, condition.CommonKeys...)...),
-
- GetObjectRetentionAction: condition.NewKeySet(condition.CommonKeys...),
- PutObjectLegalHoldAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3ObjectLockLegalHold,
- }, condition.CommonKeys...)...),
- GetObjectLegalHoldAction: condition.NewKeySet(condition.CommonKeys...),
-
- // https://docs.aws.amazon.com/AmazonS3/latest/dev/list_amazons3.html
- BypassGovernanceRetentionAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3ObjectLockRemainingRetentionDays,
- condition.S3ObjectLockRetainUntilDate,
- condition.S3ObjectLockMode,
- condition.S3ObjectLockLegalHold,
- }, condition.CommonKeys...)...),
-
- GetBucketObjectLockConfigurationAction: condition.NewKeySet(condition.CommonKeys...),
- PutBucketObjectLockConfigurationAction: condition.NewKeySet(condition.CommonKeys...),
- GetBucketTaggingAction: condition.NewKeySet(condition.CommonKeys...),
- PutBucketTaggingAction: condition.NewKeySet(condition.CommonKeys...),
- PutObjectTaggingAction: condition.NewKeySet(condition.CommonKeys...),
- GetObjectTaggingAction: condition.NewKeySet(condition.CommonKeys...),
- DeleteObjectTaggingAction: condition.NewKeySet(condition.CommonKeys...),
-
- PutObjectVersionTaggingAction: condition.NewKeySet(condition.CommonKeys...),
- GetObjectVersionAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3VersionID,
- }, condition.CommonKeys...)...),
- GetObjectVersionTaggingAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3VersionID,
- }, condition.CommonKeys...)...),
- DeleteObjectVersionAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3VersionID,
- }, condition.CommonKeys...)...),
- DeleteObjectVersionTaggingAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3VersionID,
- }, condition.CommonKeys...)...),
- GetReplicationConfigurationAction: condition.NewKeySet(condition.CommonKeys...),
- PutReplicationConfigurationAction: condition.NewKeySet(condition.CommonKeys...),
- ReplicateObjectAction: condition.NewKeySet(condition.CommonKeys...),
- ReplicateDeleteAction: condition.NewKeySet(condition.CommonKeys...),
- ReplicateTagsAction: condition.NewKeySet(condition.CommonKeys...),
- GetObjectVersionForReplicationAction: condition.NewKeySet(condition.CommonKeys...),
- RestoreObjectAction: condition.NewKeySet(condition.CommonKeys...),
-}
diff --git a/pkg/bucket/policy/action_test.go b/pkg/bucket/policy/action_test.go
deleted file mode 100644
index 1784432f0..000000000
--- a/pkg/bucket/policy/action_test.go
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package policy
-
-import (
- "encoding/json"
- "reflect"
- "testing"
-)
-
-func TestActionIsObjectAction(t *testing.T) {
- testCases := []struct {
- action Action
- expectedResult bool
- }{
- {AbortMultipartUploadAction, true},
- {DeleteObjectAction, true},
- {GetObjectAction, true},
- {ListMultipartUploadPartsAction, true},
- {PutObjectAction, true},
- {CreateBucketAction, false},
- }
-
- for i, testCase := range testCases {
- result := testCase.action.isObjectAction()
-
- if testCase.expectedResult != result {
- t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestActionIsValid(t *testing.T) {
- testCases := []struct {
- action Action
- expectedResult bool
- }{
- {AbortMultipartUploadAction, true},
- {Action("foo"), false},
- }
-
- for i, testCase := range testCases {
- result := testCase.action.IsValid()
-
- if testCase.expectedResult != result {
- t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestActionMarshalJSON(t *testing.T) {
- testCases := []struct {
- action Action
- expectedResult []byte
- expectErr bool
- }{
- {PutObjectAction, []byte(`"s3:PutObject"`), false},
- {Action("foo"), nil, true},
- }
-
- for i, testCase := range testCases {
- result, err := json.Marshal(testCase.action)
- expectErr := (err != nil)
-
- if testCase.expectErr != expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
-
-func TestActionUnmarshalJSON(t *testing.T) {
- testCases := []struct {
- data []byte
- expectedResult Action
- expectErr bool
- }{
- {[]byte(`"s3:PutObject"`), PutObjectAction, false},
- {[]byte(`"foo"`), Action(""), true},
- }
-
- for i, testCase := range testCases {
- var result Action
- err := json.Unmarshal(testCase.data, &result)
- expectErr := (err != nil)
-
- if testCase.expectErr != expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if testCase.expectedResult != result {
- t.Fatalf("case %v: result: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
diff --git a/pkg/bucket/policy/actionset.go b/pkg/bucket/policy/actionset.go
deleted file mode 100644
index 73ed286e6..000000000
--- a/pkg/bucket/policy/actionset.go
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package policy
-
-import (
- "encoding/json"
- "fmt"
- "sort"
-
- "github.com/minio/minio-go/v7/pkg/set"
-)
-
-// ActionSet - set of actions.
-type ActionSet map[Action]struct{}
-
-// Add - add action to the set.
-func (actionSet ActionSet) Add(action Action) {
- actionSet[action] = struct{}{}
-}
-
-// Contains - checks given action exists in the action set.
-func (actionSet ActionSet) Contains(action Action) bool {
- _, found := actionSet[action]
- return found
-}
-
-// Equals - checks whether given action set is equal to current action set or not.
-func (actionSet ActionSet) Equals(sactionSet ActionSet) bool {
- // If length of set is not equal to length of given set, the
- // set is not equal to given set.
- if len(actionSet) != len(sactionSet) {
- return false
- }
-
- // As both sets are equal in length, check each elements are equal.
- for k := range actionSet {
- if _, ok := sactionSet[k]; !ok {
- return false
- }
- }
-
- return true
-}
-
-// Intersection - returns actions available in both ActionSet.
-func (actionSet ActionSet) Intersection(sset ActionSet) ActionSet {
- nset := NewActionSet()
- for k := range actionSet {
- if _, ok := sset[k]; ok {
- nset.Add(k)
- }
- }
-
- return nset
-}
-
-// MarshalJSON - encodes ActionSet to JSON data.
-func (actionSet ActionSet) MarshalJSON() ([]byte, error) {
- if len(actionSet) == 0 {
- return nil, Errorf("empty actions not allowed")
- }
-
- return json.Marshal(actionSet.ToSlice())
-}
-
-func (actionSet ActionSet) String() string {
- actions := []string{}
- for action := range actionSet {
- actions = append(actions, string(action))
- }
- sort.Strings(actions)
-
- return fmt.Sprintf("%v", actions)
-}
-
-// ToSlice - returns slice of actions from the action set.
-func (actionSet ActionSet) ToSlice() []Action {
- actions := []Action{}
- for action := range actionSet {
- actions = append(actions, action)
- }
- return actions
-}
-
-// Clone clones ActionSet structure
-func (actionSet ActionSet) Clone() ActionSet {
- return NewActionSet(actionSet.ToSlice()...)
-}
-
-// UnmarshalJSON - decodes JSON data to ActionSet.
-func (actionSet *ActionSet) UnmarshalJSON(data []byte) error {
- var sset set.StringSet
- if err := json.Unmarshal(data, &sset); err != nil {
- return err
- }
-
- if len(sset) == 0 {
- return Errorf("empty actions not allowed")
- }
-
- *actionSet = make(ActionSet)
- for _, s := range sset.ToSlice() {
- action, err := parseAction(s)
- if err != nil {
- return err
- }
-
- actionSet.Add(action)
- }
-
- return nil
-}
-
-// NewActionSet - creates new action set.
-func NewActionSet(actions ...Action) ActionSet {
- actionSet := make(ActionSet)
- for _, action := range actions {
- actionSet.Add(action)
- }
-
- return actionSet
-}
diff --git a/pkg/bucket/policy/actionset_test.go b/pkg/bucket/policy/actionset_test.go
deleted file mode 100644
index 8c6ef7d10..000000000
--- a/pkg/bucket/policy/actionset_test.go
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package policy
-
-import (
- "encoding/json"
- "reflect"
- "testing"
-)
-
-func TestActionSetAdd(t *testing.T) {
- testCases := []struct {
- set ActionSet
- action Action
- expectedResult ActionSet
- }{
- {NewActionSet(), PutObjectAction, NewActionSet(PutObjectAction)},
- {NewActionSet(PutObjectAction), PutObjectAction, NewActionSet(PutObjectAction)},
- }
-
- for i, testCase := range testCases {
- testCase.set.Add(testCase.action)
-
- if !reflect.DeepEqual(testCase.expectedResult, testCase.set) {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, testCase.set)
- }
- }
-}
-
-func TestActionSetContains(t *testing.T) {
- testCases := []struct {
- set ActionSet
- action Action
- expectedResult bool
- }{
- {NewActionSet(PutObjectAction), PutObjectAction, true},
- {NewActionSet(PutObjectAction, GetObjectAction), PutObjectAction, true},
- {NewActionSet(PutObjectAction, GetObjectAction), AbortMultipartUploadAction, false},
- }
-
- for i, testCase := range testCases {
- result := testCase.set.Contains(testCase.action)
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestActionSetIntersection(t *testing.T) {
- testCases := []struct {
- set ActionSet
- setToIntersect ActionSet
- expectedResult ActionSet
- }{
- {NewActionSet(), NewActionSet(PutObjectAction), NewActionSet()},
- {NewActionSet(PutObjectAction), NewActionSet(), NewActionSet()},
- {NewActionSet(PutObjectAction), NewActionSet(PutObjectAction, GetObjectAction), NewActionSet(PutObjectAction)},
- }
-
- for i, testCase := range testCases {
- result := testCase.set.Intersection(testCase.setToIntersect)
-
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, testCase.set)
- }
- }
-}
-
-func TestActionSetMarshalJSON(t *testing.T) {
- testCases := []struct {
- actionSet ActionSet
- expectedResult []byte
- expectErr bool
- }{
- {NewActionSet(PutObjectAction), []byte(`["s3:PutObject"]`), false},
- {NewActionSet(), nil, true},
- }
-
- for i, testCase := range testCases {
- result, err := json.Marshal(testCase.actionSet)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, string(testCase.expectedResult), string(result))
- }
- }
- }
-}
-
-func TestActionSetToSlice(t *testing.T) {
- testCases := []struct {
- actionSet ActionSet
- expectedResult []Action
- }{
- {NewActionSet(PutObjectAction), []Action{PutObjectAction}},
- {NewActionSet(), []Action{}},
- }
-
- for i, testCase := range testCases {
- result := testCase.actionSet.ToSlice()
-
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestActionSetUnmarshalJSON(t *testing.T) {
- testCases := []struct {
- data []byte
- expectedResult ActionSet
- expectErr bool
- }{
- {[]byte(`"s3:PutObject"`), NewActionSet(PutObjectAction), false},
- {[]byte(`["s3:PutObject"]`), NewActionSet(PutObjectAction), false},
- {[]byte(`["s3:PutObject", "s3:GetObject"]`), NewActionSet(PutObjectAction, GetObjectAction), false},
- {[]byte(`["s3:PutObject", "s3:GetObject", "s3:PutObject"]`), NewActionSet(PutObjectAction, GetObjectAction), false},
- {[]byte(`[]`), NewActionSet(), true}, // Empty array.
- {[]byte(`"foo"`), nil, true}, // Invalid action.
- {[]byte(`["s3:PutObject", "foo"]`), nil, true}, // Invalid action.
- }
-
- for i, testCase := range testCases {
- result := make(ActionSet)
- err := json.Unmarshal(testCase.data, &result)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
diff --git a/pkg/bucket/policy/condition/binaryequalsfunc.go b/pkg/bucket/policy/condition/binaryequalsfunc.go
deleted file mode 100644
index 27991e5dc..000000000
--- a/pkg/bucket/policy/condition/binaryequalsfunc.go
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "encoding/base64"
- "fmt"
- "net/http"
- "sort"
-
- "github.com/minio/minio-go/v7/pkg/s3utils"
- "github.com/minio/minio-go/v7/pkg/set"
-)
-
-func toBinaryEqualsFuncString(n name, key Key, values set.StringSet) string {
- valueStrings := values.ToSlice()
- sort.Strings(valueStrings)
-
- return fmt.Sprintf("%v:%v:%v", n, key, valueStrings)
-}
-
-// binaryEqualsFunc - String equals function. It checks whether value by Key in given
-// values map is in condition values.
-// For example,
-// - if values = ["mybucket/foo"], at evaluate() it returns whether string
-// in value map for Key is in values.
-type binaryEqualsFunc struct {
- k Key
- values set.StringSet
-}
-
-// evaluate() - evaluates to check whether value by Key in given values is in
-// condition values.
-func (f binaryEqualsFunc) evaluate(values map[string][]string) bool {
- requestValue, ok := values[http.CanonicalHeaderKey(f.k.Name())]
- if !ok {
- requestValue = values[f.k.Name()]
- }
-
- fvalues := f.values.ApplyFunc(substFuncFromValues(values))
- return !fvalues.Intersection(set.CreateStringSet(requestValue...)).IsEmpty()
-}
-
-// key() - returns condition key which is used by this condition function.
-func (f binaryEqualsFunc) key() Key {
- return f.k
-}
-
-// name() - returns "BinaryEquals" condition name.
-func (f binaryEqualsFunc) name() name {
- return binaryEquals
-}
-
-func (f binaryEqualsFunc) String() string {
- return toBinaryEqualsFuncString(binaryEquals, f.k, f.values)
-}
-
-// toMap - returns map representation of this function.
-func (f binaryEqualsFunc) toMap() map[Key]ValueSet {
- if !f.k.IsValid() {
- return nil
- }
-
- values := NewValueSet()
- for _, value := range f.values.ToSlice() {
- values.Add(NewStringValue(base64.StdEncoding.EncodeToString([]byte(value))))
- }
-
- return map[Key]ValueSet{
- f.k: values,
- }
-}
-
-func validateBinaryEqualsValues(n name, key Key, values set.StringSet) error {
- vslice := values.ToSlice()
- for _, s := range vslice {
- sbytes, err := base64.StdEncoding.DecodeString(s)
- if err != nil {
- return err
- }
- values.Remove(s)
- s = string(sbytes)
- switch key {
- case S3XAmzCopySource:
- bucket, object := path2BucketAndObject(s)
- if object == "" {
- return fmt.Errorf("invalid value '%v' for '%v' for %v condition", s, S3XAmzCopySource, n)
- }
- if err = s3utils.CheckValidBucketName(bucket); err != nil {
- return err
- }
- case S3XAmzServerSideEncryption, S3XAmzServerSideEncryptionCustomerAlgorithm:
- if s != "AES256" {
- return fmt.Errorf("invalid value '%v' for '%v' for %v condition", s, S3XAmzServerSideEncryption, n)
- }
- case S3XAmzMetadataDirective:
- if s != "COPY" && s != "REPLACE" {
- return fmt.Errorf("invalid value '%v' for '%v' for %v condition", s, S3XAmzMetadataDirective, n)
- }
- case S3XAmzContentSha256:
- if s == "" {
- return fmt.Errorf("invalid empty value for '%v' for %v condition", S3XAmzContentSha256, n)
- }
- }
- values.Add(s)
- }
-
- return nil
-}
-
-// newBinaryEqualsFunc - returns new BinaryEquals function.
-func newBinaryEqualsFunc(key Key, values ValueSet) (Function, error) {
- valueStrings, err := valuesToStringSlice(binaryEquals, values)
- if err != nil {
- return nil, err
- }
-
- return NewBinaryEqualsFunc(key, valueStrings...)
-}
-
-// NewBinaryEqualsFunc - returns new BinaryEquals function.
-func NewBinaryEqualsFunc(key Key, values ...string) (Function, error) {
- sset := set.CreateStringSet(values...)
- if err := validateBinaryEqualsValues(binaryEquals, key, sset); err != nil {
- return nil, err
- }
-
- return &binaryEqualsFunc{key, sset}, nil
-}
diff --git a/pkg/bucket/policy/condition/binaryequalsfunc_test.go b/pkg/bucket/policy/condition/binaryequalsfunc_test.go
deleted file mode 100644
index 47e927efd..000000000
--- a/pkg/bucket/policy/condition/binaryequalsfunc_test.go
+++ /dev/null
@@ -1,383 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "encoding/base64"
- "reflect"
- "testing"
-)
-
-func TestBinaryEqualsFuncEvaluate(t *testing.T) {
- case1Function, err := newBinaryEqualsFunc(S3XAmzCopySource,
- NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("mybucket/myobject")))))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newBinaryEqualsFunc(S3XAmzServerSideEncryption,
- NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("AES256")))))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Function, err := newBinaryEqualsFunc(S3XAmzMetadataDirective,
- NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("REPLACE")))))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Function, err := newBinaryEqualsFunc(S3LocationConstraint,
- NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("eu-west-1")))))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- function Function
- values map[string][]string
- expectedResult bool
- }{
- {case1Function, map[string][]string{"x-amz-copy-source": {"mybucket/myobject"}}, true},
- {case1Function, map[string][]string{"x-amz-copy-source": {"yourbucket/myobject"}}, false},
- {case1Function, map[string][]string{}, false},
- {case1Function, map[string][]string{"delimiter": {"/"}}, false},
-
- {case2Function, map[string][]string{"x-amz-server-side-encryption": {"AES256"}}, true},
- {case2Function, map[string][]string{}, false},
- {case2Function, map[string][]string{"delimiter": {"/"}}, false},
-
- {case3Function, map[string][]string{"x-amz-metadata-directive": {"REPLACE"}}, true},
- {case3Function, map[string][]string{"x-amz-metadata-directive": {"COPY"}}, false},
- {case3Function, map[string][]string{}, false},
- {case3Function, map[string][]string{"delimiter": {"/"}}, false},
-
- {case4Function, map[string][]string{"LocationConstraint": {"eu-west-1"}}, true},
- {case4Function, map[string][]string{"LocationConstraint": {"us-east-1"}}, false},
- {case4Function, map[string][]string{}, false},
- {case4Function, map[string][]string{"delimiter": {"/"}}, false},
- }
-
- for i, testCase := range testCases {
- result := testCase.function.evaluate(testCase.values)
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestBinaryEqualsFuncKey(t *testing.T) {
- case1Function, err := newBinaryEqualsFunc(S3XAmzCopySource,
- NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("mybucket/myobject")))))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newBinaryEqualsFunc(S3XAmzServerSideEncryption,
- NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("AES256")))))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Function, err := newBinaryEqualsFunc(S3XAmzMetadataDirective,
- NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("REPLACE")))))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Function, err := newBinaryEqualsFunc(S3LocationConstraint,
- NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("eu-west-1")))))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- function Function
- expectedResult Key
- }{
- {case1Function, S3XAmzCopySource},
- {case2Function, S3XAmzServerSideEncryption},
- {case3Function, S3XAmzMetadataDirective},
- {case4Function, S3LocationConstraint},
- }
-
- for i, testCase := range testCases {
- result := testCase.function.key()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestBinaryEqualsFuncToMap(t *testing.T) {
- case1Function, err := newBinaryEqualsFunc(S3XAmzCopySource,
- NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("mybucket/myobject")))))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case1Result := map[Key]ValueSet{
- S3XAmzCopySource: NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("mybucket/myobject")))),
- }
-
- case2Function, err := newBinaryEqualsFunc(S3XAmzCopySource,
- NewValueSet(
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("mybucket/myobject"))),
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("yourbucket/myobject"))),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Result := map[Key]ValueSet{
- S3XAmzCopySource: NewValueSet(
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("mybucket/myobject"))),
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("yourbucket/myobject"))),
- ),
- }
-
- case3Function, err := newBinaryEqualsFunc(S3XAmzServerSideEncryption,
- NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("AES256")))))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Result := map[Key]ValueSet{
- S3XAmzServerSideEncryption: NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("AES256")))),
- }
-
- case4Function, err := newBinaryEqualsFunc(S3XAmzServerSideEncryption,
- NewValueSet(
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("AES256"))),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Result := map[Key]ValueSet{
- S3XAmzServerSideEncryption: NewValueSet(
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("AES256"))),
- ),
- }
-
- case5Function, err := newBinaryEqualsFunc(S3XAmzMetadataDirective,
- NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("REPLACE")))))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case5Result := map[Key]ValueSet{
- S3XAmzMetadataDirective: NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("REPLACE")))),
- }
-
- case6Function, err := newBinaryEqualsFunc(S3XAmzMetadataDirective,
- NewValueSet(
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("REPLACE"))),
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("COPY"))),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case6Result := map[Key]ValueSet{
- S3XAmzMetadataDirective: NewValueSet(
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("REPLACE"))),
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("COPY"))),
- ),
- }
-
- case7Function, err := newBinaryEqualsFunc(S3LocationConstraint,
- NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("eu-west-1")))))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case7Result := map[Key]ValueSet{
- S3LocationConstraint: NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("eu-west-1")))),
- }
-
- case8Function, err := newBinaryEqualsFunc(S3LocationConstraint,
- NewValueSet(
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("eu-west-1"))),
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("us-west-1"))),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case8Result := map[Key]ValueSet{
- S3LocationConstraint: NewValueSet(
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("eu-west-1"))),
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("us-west-1"))),
- ),
- }
-
- testCases := []struct {
- f Function
- expectedResult map[Key]ValueSet
- }{
- {case1Function, case1Result},
- {case2Function, case2Result},
- {case3Function, case3Result},
- {case4Function, case4Result},
- {case5Function, case5Result},
- {case6Function, case6Result},
- {case7Function, case7Result},
- {case8Function, case8Result},
- {&binaryEqualsFunc{}, nil},
- }
-
- for i, testCase := range testCases {
- result := testCase.f.toMap()
-
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestNewBinaryEqualsFunc(t *testing.T) {
- case1Function, err := newBinaryEqualsFunc(S3XAmzCopySource,
- NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("mybucket/myobject")))))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newBinaryEqualsFunc(S3XAmzCopySource,
- NewValueSet(
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("mybucket/myobject"))),
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("yourbucket/myobject"))),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Function, err := newBinaryEqualsFunc(S3XAmzServerSideEncryption,
- NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("AES256")))))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Function, err := newBinaryEqualsFunc(S3XAmzServerSideEncryption,
- NewValueSet(
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("AES256"))),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case5Function, err := newBinaryEqualsFunc(S3XAmzMetadataDirective,
- NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("REPLACE")))))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case6Function, err := newBinaryEqualsFunc(S3XAmzMetadataDirective,
- NewValueSet(
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("REPLACE"))),
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("COPY"))),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case7Function, err := newBinaryEqualsFunc(S3LocationConstraint,
- NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("eu-west-1")))))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case8Function, err := newBinaryEqualsFunc(S3LocationConstraint,
- NewValueSet(
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("eu-west-1"))),
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("us-west-1"))),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- key Key
- values ValueSet
- expectedResult Function
- expectErr bool
- }{
- {S3XAmzCopySource, NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("mybucket/myobject")))), case1Function, false},
- {S3XAmzCopySource,
- NewValueSet(
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("mybucket/myobject"))),
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("yourbucket/myobject"))),
- ), case2Function, false},
-
- {S3XAmzServerSideEncryption, NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("AES256")))), case3Function, false},
- {S3XAmzServerSideEncryption,
- NewValueSet(
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("AES256"))),
- ), case4Function, false},
-
- {S3XAmzMetadataDirective, NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("REPLACE")))), case5Function, false},
- {S3XAmzMetadataDirective,
- NewValueSet(
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("REPLACE"))),
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("COPY"))),
- ), case6Function, false},
-
- {S3LocationConstraint, NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("eu-west-1")))), case7Function, false},
- {S3LocationConstraint,
- NewValueSet(
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("eu-west-1"))),
- NewStringValue(base64.StdEncoding.EncodeToString([]byte("us-west-1"))),
- ), case8Function, false},
-
- // Unsupported value error.
- {S3XAmzCopySource, NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("mybucket/myobject"))), NewIntValue(7)), nil, true},
- {S3XAmzServerSideEncryption, NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("AES256"))), NewIntValue(7)), nil, true},
- {S3XAmzMetadataDirective, NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("REPLACE"))), NewIntValue(7)), nil, true},
- {S3LocationConstraint, NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("eu-west-1"))), NewIntValue(7)), nil, true},
-
- // Invalid value error.
- {S3XAmzCopySource, NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("mybucket")))), nil, true},
- {S3XAmzServerSideEncryption, NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("SSE-C")))), nil, true},
- {S3XAmzMetadataDirective, NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("DUPLICATE")))), nil, true},
- }
-
- for i, testCase := range testCases {
- result, err := newBinaryEqualsFunc(testCase.key, testCase.values)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
diff --git a/pkg/bucket/policy/condition/boolfunc.go b/pkg/bucket/policy/condition/boolfunc.go
deleted file mode 100644
index b0e49e513..000000000
--- a/pkg/bucket/policy/condition/boolfunc.go
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "fmt"
- "net/http"
- "reflect"
- "strconv"
-)
-
-// booleanFunc - Bool condition function. It checks whether Key is true or false.
-// https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition_operators.html#Conditions_Boolean
-type booleanFunc struct {
- k Key
- value string
-}
-
-// evaluate() - evaluates to check whether Key is present in given values or not.
-// Depending on condition boolean value, this function returns true or false.
-func (f booleanFunc) evaluate(values map[string][]string) bool {
- requestValue, ok := values[http.CanonicalHeaderKey(f.k.Name())]
- if !ok {
- requestValue = values[f.k.Name()]
- }
-
- if len(requestValue) == 0 {
- return false
- }
-
- return f.value == requestValue[0]
-}
-
-// key() - returns condition key which is used by this condition function.
-func (f booleanFunc) key() Key {
- return f.k
-}
-
-// name() - returns "Bool" condition name.
-func (f booleanFunc) name() name {
- return boolean
-}
-
-func (f booleanFunc) String() string {
- return fmt.Sprintf("%v:%v:%v", boolean, f.k, f.value)
-}
-
-// toMap - returns map representation of this function.
-func (f booleanFunc) toMap() map[Key]ValueSet {
- if !f.k.IsValid() {
- return nil
- }
-
- return map[Key]ValueSet{
- f.k: NewValueSet(NewStringValue(f.value)),
- }
-}
-
-func newBooleanFunc(key Key, values ValueSet) (Function, error) {
- if key != AWSSecureTransport {
- return nil, fmt.Errorf("only %v key is allowed for %v condition", AWSSecureTransport, boolean)
- }
-
- if len(values) != 1 {
- return nil, fmt.Errorf("only one value is allowed for boolean condition")
- }
-
- var value Value
- for v := range values {
- value = v
- switch v.GetType() {
- case reflect.Bool:
- if _, err := v.GetBool(); err != nil {
- return nil, err
- }
- case reflect.String:
- s, err := v.GetString()
- if err != nil {
- return nil, err
- }
- if _, err = strconv.ParseBool(s); err != nil {
- return nil, fmt.Errorf("value must be a boolean string for boolean condition")
- }
- default:
- return nil, fmt.Errorf("value must be a boolean for boolean condition")
- }
- }
-
- return &booleanFunc{key, value.String()}, nil
-}
-
-// NewBoolFunc - returns new Bool function.
-func NewBoolFunc(key Key, value string) (Function, error) {
- return &booleanFunc{key, value}, nil
-}
diff --git a/pkg/bucket/policy/condition/boolfunc_test.go b/pkg/bucket/policy/condition/boolfunc_test.go
deleted file mode 100644
index 49a6ef8b7..000000000
--- a/pkg/bucket/policy/condition/boolfunc_test.go
+++ /dev/null
@@ -1,153 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "reflect"
- "testing"
-)
-
-func TestBooleanFuncEvaluate(t *testing.T) {
- case1Function, err := newBooleanFunc(AWSSecureTransport, NewValueSet(NewBoolValue(true)))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newBooleanFunc(AWSSecureTransport, NewValueSet(NewBoolValue(false)))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- function Function
- values map[string][]string
- expectedResult bool
- }{
- {case1Function, map[string][]string{"SecureTransport": {"true"}}, true},
- {case2Function, map[string][]string{"SecureTransport": {"false"}}, true},
- }
-
- for i, testCase := range testCases {
- result := testCase.function.evaluate(testCase.values)
-
- if result != testCase.expectedResult {
- t.Errorf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestBooleanFuncKey(t *testing.T) {
- case1Function, err := newBooleanFunc(AWSSecureTransport, NewValueSet(NewBoolValue(true)))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- function Function
- expectedResult Key
- }{
- {case1Function, AWSSecureTransport},
- }
-
- for i, testCase := range testCases {
- result := testCase.function.key()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestBooleanFuncToMap(t *testing.T) {
- case1Function, err := newBooleanFunc(AWSSecureTransport, NewValueSet(NewBoolValue(true)))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case1Result := map[Key]ValueSet{
- AWSSecureTransport: NewValueSet(NewStringValue("true")),
- }
-
- case2Function, err := newBooleanFunc(AWSSecureTransport, NewValueSet(NewBoolValue(false)))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Result := map[Key]ValueSet{
- AWSSecureTransport: NewValueSet(NewStringValue("false")),
- }
-
- testCases := []struct {
- f Function
- expectedResult map[Key]ValueSet
- }{
- {case1Function, case1Result},
- {case2Function, case2Result},
- }
-
- for i, testCase := range testCases {
- result := testCase.f.toMap()
-
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestNewBooleanFunc(t *testing.T) {
- case1Function, err := newBooleanFunc(AWSSecureTransport, NewValueSet(NewBoolValue(true)))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newBooleanFunc(AWSSecureTransport, NewValueSet(NewBoolValue(false)))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- key Key
- values ValueSet
- expectedResult Function
- expectErr bool
- }{
- {AWSSecureTransport, NewValueSet(NewBoolValue(true)), case1Function, false},
- {AWSSecureTransport, NewValueSet(NewStringValue("false")), case2Function, false},
- // Multiple values error.
- {AWSSecureTransport, NewValueSet(NewStringValue("true"), NewStringValue("false")), nil, true},
- // Invalid boolean string error.
- {AWSSecureTransport, NewValueSet(NewStringValue("foo")), nil, true},
- // Invalid value error.
- {AWSSecureTransport, NewValueSet(NewIntValue(7)), nil, true},
- }
-
- for i, testCase := range testCases {
- result, err := newBooleanFunc(testCase.key, testCase.values)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
diff --git a/pkg/bucket/policy/condition/dateequalsfunc.go b/pkg/bucket/policy/condition/dateequalsfunc.go
deleted file mode 100644
index b9a0b2e1a..000000000
--- a/pkg/bucket/policy/condition/dateequalsfunc.go
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "fmt"
- "net/http"
- "reflect"
- "time"
-)
-
-func toDateEqualsFuncString(n name, key Key, value time.Time) string {
- return fmt.Sprintf("%v:%v:%v", n, key, value.Format(time.RFC3339))
-}
-
-// dateEqualsFunc - String equals function. It checks whether value by Key in given
-// values map is in condition values.
-// For example,
-// - if values = ["mybucket/foo"], at evaluate() it returns whether string
-// in value map for Key is in values.
-type dateEqualsFunc struct {
- k Key
- value time.Time
-}
-
-// evaluate() - evaluates to check whether value by Key in given values is in
-// condition values.
-func (f dateEqualsFunc) evaluate(values map[string][]string) bool {
- requestValue, ok := values[http.CanonicalHeaderKey(f.k.Name())]
- if !ok {
- requestValue = values[f.k.Name()]
- }
-
- if len(requestValue) == 0 {
- return false
- }
-
- t, err := time.Parse(time.RFC3339, requestValue[0])
- if err != nil {
- return false
- }
-
- return f.value.Equal(t)
-}
-
-// key() - returns condition key which is used by this condition function.
-func (f dateEqualsFunc) key() Key {
- return f.k
-}
-
-// name() - returns "DateEquals" condition name.
-func (f dateEqualsFunc) name() name {
- return dateEquals
-}
-
-func (f dateEqualsFunc) String() string {
- return toDateEqualsFuncString(dateEquals, f.k, f.value)
-}
-
-// toMap - returns map representation of this function.
-func (f dateEqualsFunc) toMap() map[Key]ValueSet {
- if !f.k.IsValid() {
- return nil
- }
-
- values := NewValueSet()
- values.Add(NewStringValue(f.value.Format(time.RFC3339)))
-
- return map[Key]ValueSet{
- f.k: values,
- }
-}
-
-// dateNotEqualsFunc - String not equals function. It checks whether value by Key in
-// given values is NOT in condition values.
-// For example,
-// - if values = ["mybucket/foo"], at evaluate() it returns whether string
-// in value map for Key is NOT in values.
-type dateNotEqualsFunc struct {
- dateEqualsFunc
-}
-
-// evaluate() - evaluates to check whether value by Key in given values is NOT in
-// condition values.
-func (f dateNotEqualsFunc) evaluate(values map[string][]string) bool {
- return !f.dateEqualsFunc.evaluate(values)
-}
-
-// name() - returns "DateNotEquals" condition name.
-func (f dateNotEqualsFunc) name() name {
- return dateNotEquals
-}
-
-func (f dateNotEqualsFunc) String() string {
- return toDateEqualsFuncString(dateNotEquals, f.dateEqualsFunc.k, f.dateEqualsFunc.value)
-}
-
-func valueToTime(n name, values ValueSet) (v time.Time, err error) {
- if len(values) != 1 {
- return v, fmt.Errorf("only one value is allowed for %s condition", n)
- }
-
- for vs := range values {
- switch vs.GetType() {
- case reflect.String:
- s, err := vs.GetString()
- if err != nil {
- return v, err
- }
- if v, err = time.Parse(time.RFC3339, s); err != nil {
- return v, fmt.Errorf("value %s must be a time.Time string for %s condition: %w", vs, n, err)
- }
- default:
- return v, fmt.Errorf("value %s must be a time.Time for %s condition", vs, n)
- }
- }
-
- return v, nil
-
-}
-
-// newDateEqualsFunc - returns new DateEquals function.
-func newDateEqualsFunc(key Key, values ValueSet) (Function, error) {
- v, err := valueToTime(dateEquals, values)
- if err != nil {
- return nil, err
- }
-
- return NewDateEqualsFunc(key, v)
-}
-
-// NewDateEqualsFunc - returns new DateEquals function.
-func NewDateEqualsFunc(key Key, value time.Time) (Function, error) {
- return &dateEqualsFunc{key, value}, nil
-}
-
-// newDateNotEqualsFunc - returns new DateNotEquals function.
-func newDateNotEqualsFunc(key Key, values ValueSet) (Function, error) {
- v, err := valueToTime(dateNotEquals, values)
- if err != nil {
- return nil, err
- }
-
- return NewDateNotEqualsFunc(key, v)
-}
-
-// NewDateNotEqualsFunc - returns new DateNotEquals function.
-func NewDateNotEqualsFunc(key Key, value time.Time) (Function, error) {
- return &dateNotEqualsFunc{dateEqualsFunc{key, value}}, nil
-}
diff --git a/pkg/bucket/policy/condition/dategreaterthanfunc.go b/pkg/bucket/policy/condition/dategreaterthanfunc.go
deleted file mode 100644
index ca18c4c6e..000000000
--- a/pkg/bucket/policy/condition/dategreaterthanfunc.go
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "fmt"
- "net/http"
- "time"
-)
-
-func toDateGreaterThanFuncString(n name, key Key, value time.Time) string {
- return fmt.Sprintf("%v:%v:%v", n, key, value.Format(time.RFC3339))
-}
-
-// dateGreaterThanFunc - String equals function. It checks whether value by Key in given
-// values map is in condition values.
-// For example,
-// - if values = ["mybucket/foo"], at evaluate() it returns whether string
-// in value map for Key is in values.
-type dateGreaterThanFunc struct {
- k Key
- value time.Time
-}
-
-// evaluate() - evaluates to check whether value by Key in given values is in
-// condition values.
-func (f dateGreaterThanFunc) evaluate(values map[string][]string) bool {
- requestValue, ok := values[http.CanonicalHeaderKey(f.k.Name())]
- if !ok {
- requestValue = values[f.k.Name()]
- }
-
- if len(requestValue) == 0 {
- return false
- }
-
- t, err := time.Parse(time.RFC3339, requestValue[0])
- if err != nil {
- return false
- }
-
- return t.After(f.value)
-}
-
-// key() - returns condition key which is used by this condition function.
-func (f dateGreaterThanFunc) key() Key {
- return f.k
-}
-
-// name() - returns "DateGreaterThan" condition name.
-func (f dateGreaterThanFunc) name() name {
- return dateGreaterThan
-}
-
-func (f dateGreaterThanFunc) String() string {
- return toDateGreaterThanFuncString(dateGreaterThan, f.k, f.value)
-}
-
-// toMap - returns map representation of this function.
-func (f dateGreaterThanFunc) toMap() map[Key]ValueSet {
- if !f.k.IsValid() {
- return nil
- }
-
- values := NewValueSet()
- values.Add(NewStringValue(f.value.Format(time.RFC3339)))
-
- return map[Key]ValueSet{
- f.k: values,
- }
-}
-
-// dateNotEqualsFunc - String not equals function. It checks whether value by Key in
-// given values is NOT in condition values.
-// For example,
-// - if values = ["mybucket/foo"], at evaluate() it returns whether string
-// in value map for Key is NOT in values.
-type dateGreaterThanEqualsFunc struct {
- dateGreaterThanFunc
-}
-
-// evaluate() - evaluates to check whether value by Key in given values is NOT in
-// condition values.
-func (f dateGreaterThanEqualsFunc) evaluate(values map[string][]string) bool {
- requestValue, ok := values[http.CanonicalHeaderKey(f.k.Name())]
- if !ok {
- requestValue = values[f.k.Name()]
- }
-
- if len(requestValue) == 0 {
- return false
- }
-
- t, err := time.Parse(time.RFC3339, requestValue[0])
- if err != nil {
- return false
- }
-
- return t.After(f.value) || t.Equal(f.value)
-}
-
-// name() - returns "DateNotEquals" condition name.
-func (f dateGreaterThanEqualsFunc) name() name {
- return dateGreaterThanEquals
-}
-
-func (f dateGreaterThanEqualsFunc) String() string {
- return toDateGreaterThanFuncString(dateNotEquals, f.dateGreaterThanFunc.k, f.dateGreaterThanFunc.value)
-}
-
-// newDateGreaterThanFunc - returns new DateGreaterThan function.
-func newDateGreaterThanFunc(key Key, values ValueSet) (Function, error) {
- v, err := valueToTime(dateGreaterThan, values)
- if err != nil {
- return nil, err
- }
-
- return NewDateGreaterThanFunc(key, v)
-}
-
-// NewDateGreaterThanFunc - returns new DateGreaterThan function.
-func NewDateGreaterThanFunc(key Key, value time.Time) (Function, error) {
- return &dateGreaterThanFunc{key, value}, nil
-}
-
-// newDateNotEqualsFunc - returns new DateNotEquals function.
-func newDateGreaterThanEqualsFunc(key Key, values ValueSet) (Function, error) {
- v, err := valueToTime(dateNotEquals, values)
- if err != nil {
- return nil, err
- }
-
- return NewDateGreaterThanEqualsFunc(key, v)
-}
-
-// NewDateGreaterThanEqualsFunc - returns new DateNotEquals function.
-func NewDateGreaterThanEqualsFunc(key Key, value time.Time) (Function, error) {
- return &dateGreaterThanEqualsFunc{dateGreaterThanFunc{key, value}}, nil
-}
diff --git a/pkg/bucket/policy/condition/datelessthanfunc.go b/pkg/bucket/policy/condition/datelessthanfunc.go
deleted file mode 100644
index 0151cfa2c..000000000
--- a/pkg/bucket/policy/condition/datelessthanfunc.go
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "fmt"
- "net/http"
- "time"
-)
-
-func toDateLessThanFuncString(n name, key Key, value time.Time) string {
- return fmt.Sprintf("%v:%v:%v", n, key, value.Format(time.RFC3339))
-}
-
-// dateLessThanFunc - String equals function. It checks whether value by Key in given
-// values map is in condition values.
-// For example,
-// - if values = ["mybucket/foo"], at evaluate() it returns whether string
-// in value map for Key is in values.
-type dateLessThanFunc struct {
- k Key
- value time.Time
-}
-
-// evaluate() - evaluates to check whether value by Key in given values is in
-// condition values.
-func (f dateLessThanFunc) evaluate(values map[string][]string) bool {
- requestValue, ok := values[http.CanonicalHeaderKey(f.k.Name())]
- if !ok {
- requestValue = values[f.k.Name()]
- }
-
- if len(requestValue) == 0 {
- return false
- }
-
- t, err := time.Parse(time.RFC3339, requestValue[0])
- if err != nil {
- return false
- }
-
- return t.Before(f.value)
-}
-
-// key() - returns condition key which is used by this condition function.
-func (f dateLessThanFunc) key() Key {
- return f.k
-}
-
-// name() - returns "DateLessThan" condition name.
-func (f dateLessThanFunc) name() name {
- return dateLessThan
-}
-
-func (f dateLessThanFunc) String() string {
- return toDateLessThanFuncString(dateLessThan, f.k, f.value)
-}
-
-// toMap - returns map representation of this function.
-func (f dateLessThanFunc) toMap() map[Key]ValueSet {
- if !f.k.IsValid() {
- return nil
- }
-
- values := NewValueSet()
- values.Add(NewStringValue(f.value.Format(time.RFC3339)))
-
- return map[Key]ValueSet{
- f.k: values,
- }
-}
-
-// dateNotEqualsFunc - String not equals function. It checks whether value by Key in
-// given values is NOT in condition values.
-// For example,
-// - if values = ["mybucket/foo"], at evaluate() it returns whether string
-// in value map for Key is NOT in values.
-type dateLessThanEqualsFunc struct {
- dateLessThanFunc
-}
-
-// evaluate() - evaluates to check whether value by Key in given values is NOT in
-// condition values.
-func (f dateLessThanEqualsFunc) evaluate(values map[string][]string) bool {
- requestValue, ok := values[http.CanonicalHeaderKey(f.k.Name())]
- if !ok {
- requestValue = values[f.k.Name()]
- }
-
- if len(requestValue) == 0 {
- return false
- }
-
- t, err := time.Parse(time.RFC3339, requestValue[0])
- if err != nil {
- return false
- }
-
- return t.Before(f.value) || t.Equal(f.value)
-}
-
-// name() - returns "DateNotEquals" condition name.
-func (f dateLessThanEqualsFunc) name() name {
- return dateLessThanEquals
-}
-
-func (f dateLessThanEqualsFunc) String() string {
- return toDateLessThanFuncString(dateNotEquals, f.dateLessThanFunc.k, f.dateLessThanFunc.value)
-}
-
-// newDateLessThanFunc - returns new DateLessThan function.
-func newDateLessThanFunc(key Key, values ValueSet) (Function, error) {
- v, err := valueToTime(dateLessThan, values)
- if err != nil {
- return nil, err
- }
-
- return NewDateLessThanFunc(key, v)
-}
-
-// NewDateLessThanFunc - returns new DateLessThan function.
-func NewDateLessThanFunc(key Key, value time.Time) (Function, error) {
- return &dateLessThanFunc{key, value}, nil
-}
-
-// newDateNotEqualsFunc - returns new DateNotEquals function.
-func newDateLessThanEqualsFunc(key Key, values ValueSet) (Function, error) {
- v, err := valueToTime(dateNotEquals, values)
- if err != nil {
- return nil, err
- }
-
- return NewDateLessThanEqualsFunc(key, v)
-}
-
-// NewDateLessThanEqualsFunc - returns new DateNotEquals function.
-func NewDateLessThanEqualsFunc(key Key, value time.Time) (Function, error) {
- return &dateLessThanEqualsFunc{dateLessThanFunc{key, value}}, nil
-}
diff --git a/pkg/bucket/policy/condition/func.go b/pkg/bucket/policy/condition/func.go
deleted file mode 100644
index e6c0a3c22..000000000
--- a/pkg/bucket/policy/condition/func.go
+++ /dev/null
@@ -1,224 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "encoding/json"
- "fmt"
- "sort"
-)
-
-// Function - condition function interface.
-type Function interface {
- // evaluate() - evaluates this condition function with given values.
- evaluate(values map[string][]string) bool
-
- // key() - returns condition key used in this function.
- key() Key
-
- // name() - returns condition name of this function.
- name() name
-
- // String() - returns string representation of function.
- String() string
-
- // toMap - returns map representation of this function.
- toMap() map[Key]ValueSet
-}
-
-// Functions - list of functions.
-type Functions []Function
-
-// Evaluate - evaluates all functions with given values map. Each function is evaluated
-// sequencely and next function is called only if current function succeeds.
-func (functions Functions) Evaluate(values map[string][]string) bool {
- for _, f := range functions {
- if !f.evaluate(values) {
- return false
- }
- }
-
- return true
-}
-
-// Keys - returns list of keys used in all functions.
-func (functions Functions) Keys() KeySet {
- keySet := NewKeySet()
-
- for _, f := range functions {
- keySet.Add(f.key())
- }
-
- return keySet
-}
-
-// Clone clones Functions structure
-func (functions Functions) Clone() Functions {
- funcs := []Function{}
-
- for _, f := range functions {
- vfn := conditionFuncMap[f.name()]
- for key, values := range f.toMap() {
- function, _ := vfn(key, values.Clone())
- funcs = append(funcs, function)
- }
- }
-
- return funcs
-}
-
-// Equals returns true if two Functions structures are equal
-func (functions Functions) Equals(funcs Functions) bool {
- if len(functions) != len(funcs) {
- return false
- }
- for _, fi := range functions {
- fistr := fi.String()
- found := false
- for _, fj := range funcs {
- if fistr == fj.String() {
- found = true
- break
- }
- }
- if !found {
- return false
- }
- }
- return true
-}
-
-// MarshalJSON - encodes Functions to JSON data.
-func (functions Functions) MarshalJSON() ([]byte, error) {
- nm := make(map[name]map[Key]ValueSet)
-
- for _, f := range functions {
- if _, ok := nm[f.name()]; ok {
- for k, v := range f.toMap() {
- nm[f.name()][k] = v
- }
- } else {
- nm[f.name()] = f.toMap()
- }
- }
-
- return json.Marshal(nm)
-}
-
-func (functions Functions) String() string {
- funcStrings := []string{}
- for _, f := range functions {
- s := fmt.Sprintf("%v", f)
- funcStrings = append(funcStrings, s)
- }
- sort.Strings(funcStrings)
-
- return fmt.Sprintf("%v", funcStrings)
-}
-
-var conditionFuncMap = map[name]func(Key, ValueSet) (Function, error){
- stringEquals: newStringEqualsFunc,
- stringNotEquals: newStringNotEqualsFunc,
- stringEqualsIgnoreCase: newStringEqualsIgnoreCaseFunc,
- stringNotEqualsIgnoreCase: newStringNotEqualsIgnoreCaseFunc,
- binaryEquals: newBinaryEqualsFunc,
- stringLike: newStringLikeFunc,
- stringNotLike: newStringNotLikeFunc,
- ipAddress: newIPAddressFunc,
- notIPAddress: newNotIPAddressFunc,
- null: newNullFunc,
- boolean: newBooleanFunc,
- numericEquals: newNumericEqualsFunc,
- numericNotEquals: newNumericNotEqualsFunc,
- numericLessThan: newNumericLessThanFunc,
- numericLessThanEquals: newNumericLessThanEqualsFunc,
- numericGreaterThan: newNumericGreaterThanFunc,
- numericGreaterThanEquals: newNumericGreaterThanEqualsFunc,
- dateEquals: newDateEqualsFunc,
- dateNotEquals: newDateNotEqualsFunc,
- dateLessThan: newDateLessThanFunc,
- dateLessThanEquals: newDateLessThanEqualsFunc,
- dateGreaterThan: newDateGreaterThanFunc,
- dateGreaterThanEquals: newDateGreaterThanEqualsFunc,
- // Add new conditions here.
-}
-
-// UnmarshalJSON - decodes JSON data to Functions.
-func (functions *Functions) UnmarshalJSON(data []byte) error {
- // As string kind, int kind then json.Unmarshaler is checked at
- // https://github.com/golang/go/blob/master/src/encoding/json/decode.go#L618
- // UnmarshalJSON() is not called for types extending string
- // see https://play.golang.org/p/HrSsKksHvrS, better way to do is
- // https://play.golang.org/p/y9ElWpBgVAB
- //
- // Due to this issue, name and Key types cannot be used as map keys below.
- nm := make(map[string]map[string]ValueSet)
- if err := json.Unmarshal(data, &nm); err != nil {
- return err
- }
-
- if len(nm) == 0 {
- return fmt.Errorf("condition must not be empty")
- }
-
- funcs := []Function{}
- for nameString, args := range nm {
- n, err := parseName(nameString)
- if err != nil {
- return err
- }
-
- for keyString, values := range args {
- key, err := parseKey(keyString)
- if err != nil {
- return err
- }
-
- vfn, ok := conditionFuncMap[n]
- if !ok {
- return fmt.Errorf("condition %v is not handled", n)
- }
-
- f, err := vfn(key, values)
- if err != nil {
- return err
- }
-
- funcs = append(funcs, f)
- }
- }
-
- *functions = funcs
-
- return nil
-}
-
-// GobEncode - encodes Functions to gob data.
-func (functions Functions) GobEncode() ([]byte, error) {
- return functions.MarshalJSON()
-}
-
-// GobDecode - decodes gob data to Functions.
-func (functions *Functions) GobDecode(data []byte) error {
- return functions.UnmarshalJSON(data)
-}
-
-// NewFunctions - returns new Functions with given function list.
-func NewFunctions(functions ...Function) Functions {
- return Functions(functions)
-}
diff --git a/pkg/bucket/policy/condition/func_test.go b/pkg/bucket/policy/condition/func_test.go
deleted file mode 100644
index 4bfdc92f5..000000000
--- a/pkg/bucket/policy/condition/func_test.go
+++ /dev/null
@@ -1,354 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "encoding/json"
- "reflect"
- "testing"
-)
-
-func TestFunctionsEvaluate(t *testing.T) {
- func1, err := newNullFunc(S3XAmzCopySource, NewValueSet(NewBoolValue(true)))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- func2, err := newIPAddressFunc(AWSSourceIP, NewValueSet(NewStringValue("192.168.1.0/24")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- func3, err := newStringEqualsFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- func4, err := newStringLikeFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case1Function := NewFunctions(func1, func2, func3, func4)
-
- testCases := []struct {
- functions Functions
- values map[string][]string
- expectedResult bool
- }{
- {case1Function, map[string][]string{
- "x-amz-copy-source": {"mybucket/myobject"},
- "SourceIp": {"192.168.1.10"},
- }, false},
- {case1Function, map[string][]string{
- "x-amz-copy-source": {"mybucket/myobject"},
- "SourceIp": {"192.168.1.10"},
- "Refer": {"http://example.org/"},
- }, false},
- {case1Function, map[string][]string{"x-amz-copy-source": {"mybucket/myobject"}}, false},
- {case1Function, map[string][]string{"SourceIp": {"192.168.1.10"}}, false},
- {case1Function, map[string][]string{
- "x-amz-copy-source": {"mybucket/yourobject"},
- "SourceIp": {"192.168.1.10"},
- }, false},
- {case1Function, map[string][]string{
- "x-amz-copy-source": {"mybucket/myobject"},
- "SourceIp": {"192.168.2.10"},
- }, false},
- {case1Function, map[string][]string{
- "x-amz-copy-source": {"mybucket/myobject"},
- "Refer": {"http://example.org/"},
- }, false},
- }
-
- for i, testCase := range testCases {
- result := testCase.functions.Evaluate(testCase.values)
-
- if result != testCase.expectedResult {
- t.Errorf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestFunctionsKeys(t *testing.T) {
- func1, err := newNullFunc(S3XAmzCopySource, NewValueSet(NewBoolValue(true)))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- func2, err := newIPAddressFunc(AWSSourceIP, NewValueSet(NewStringValue("192.168.1.0/24")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- func3, err := newStringEqualsFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- func4, err := newStringLikeFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- functions Functions
- expectedResult KeySet
- }{
- {NewFunctions(func1, func2, func3, func4), NewKeySet(S3XAmzCopySource, AWSSourceIP)},
- }
-
- for i, testCase := range testCases {
- result := testCase.functions.Keys()
-
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestFunctionsMarshalJSON(t *testing.T) {
- func1, err := newStringLikeFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPL*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- func2, err := newStringEqualsFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- func3, err := newStringNotEqualsFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- func4, err := newNotIPAddressFunc(AWSSourceIP,
- NewValueSet(NewStringValue("10.1.10.0/24")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- func5, err := newStringNotLikeFunc(S3XAmzStorageClass, NewValueSet(NewStringValue("STANDARD")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- func6, err := newNullFunc(S3XAmzServerSideEncryptionCustomerAlgorithm, NewValueSet(NewBoolValue(true)))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- func7, err := newIPAddressFunc(AWSSourceIP,
- NewValueSet(NewStringValue("192.168.1.0/24")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case1Result := []byte(`{"IpAddress":{"aws:SourceIp":["192.168.1.0/24"]},"NotIpAddress":{"aws:SourceIp":["10.1.10.0/24"]},"Null":{"s3:x-amz-server-side-encryption-customer-algorithm":[true]},"StringEquals":{"s3:x-amz-copy-source":["mybucket/myobject"]},"StringLike":{"s3:x-amz-metadata-directive":["REPL*"]},"StringNotEquals":{"s3:x-amz-server-side-encryption":["AES256"]},"StringNotLike":{"s3:x-amz-storage-class":["STANDARD"]}}`)
-
- case2Result := []byte(`{"Null":{"s3:x-amz-server-side-encryption-customer-algorithm":[true]}}`)
-
- testCases := []struct {
- functions Functions
- expectedResult []byte
- expectErr bool
- }{
- {NewFunctions(func1, func2, func3, func4, func5, func6, func7), case1Result, false},
- {NewFunctions(func6), case2Result, false},
- {NewFunctions(), []byte(`{}`), false},
- {nil, []byte(`{}`), false},
- }
-
- for i, testCase := range testCases {
- result, err := json.Marshal(testCase.functions)
- expectErr := (err != nil)
-
- if testCase.expectErr != expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v", i+1, string(testCase.expectedResult), string(result))
- }
- }
- }
-}
-
-func TestFunctionsUnmarshalJSON(t *testing.T) {
- case1Data := []byte(`{
- "StringLike": {
- "s3:x-amz-metadata-directive": "REPL*"
- },
- "StringEquals": {
- "s3:x-amz-copy-source": "mybucket/myobject"
- },
- "StringNotEquals": {
- "s3:x-amz-server-side-encryption": "AES256"
- },
- "NotIpAddress": {
- "aws:SourceIp": [
- "10.1.10.0/24",
- "10.10.1.0/24"
- ]
- },
- "StringNotLike": {
- "s3:x-amz-storage-class": "STANDARD"
- },
- "Null": {
- "s3:x-amz-server-side-encryption-customer-algorithm": true
- },
- "IpAddress": {
- "aws:SourceIp": [
- "192.168.1.0/24",
- "192.168.2.0/24"
- ]
- }
-}`)
- func1, err := newStringLikeFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPL*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- func2, err := newStringEqualsFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- func3, err := newStringNotEqualsFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- func4, err := newNotIPAddressFunc(AWSSourceIP,
- NewValueSet(NewStringValue("10.1.10.0/24"), NewStringValue("10.10.1.0/24")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- func5, err := newStringNotLikeFunc(S3XAmzStorageClass, NewValueSet(NewStringValue("STANDARD")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- func6, err := newNullFunc(S3XAmzServerSideEncryptionCustomerAlgorithm, NewValueSet(NewBoolValue(true)))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- func7, err := newIPAddressFunc(AWSSourceIP,
- NewValueSet(NewStringValue("192.168.1.0/24"), NewStringValue("192.168.2.0/24")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Data := []byte(`{
- "Null": {
- "s3:x-amz-server-side-encryption-customer-algorithm": true
- },
- "Null": {
- "s3:x-amz-server-side-encryption-customer-algorithm": "true"
- }
-}`)
-
- case3Data := []byte(`{}`)
-
- case4Data := []byte(`{
- "StringLike": {
- "s3:x-amz-metadata-directive": "REPL*"
- },
- "StringEquals": {
- "s3:x-amz-copy-source": "mybucket/myobject",
- "s3:prefix": [
- "",
- "home/"
- ],
- "s3:delimiter": [
- "/"
- ]
- },
- "StringNotEquals": {
- "s3:x-amz-server-side-encryption": "AES256"
- },
- "NotIpAddress": {
- "aws:SourceIp": [
- "10.1.10.0/24",
- "10.10.1.0/24"
- ]
- },
- "StringNotLike": {
- "s3:x-amz-storage-class": "STANDARD"
- },
- "Null": {
- "s3:x-amz-server-side-encryption-customer-algorithm": true
- },
- "IpAddress": {
- "aws:SourceIp": [
- "192.168.1.0/24",
- "192.168.2.0/24"
- ]
- }
-}`)
-
- func2_1, err := newStringEqualsFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- func2_2, err := newStringEqualsFunc(S3Prefix, NewValueSet(NewStringValue(""), NewStringValue("home/")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- func2_3, err := newStringEqualsFunc(S3Delimiter, NewValueSet(NewStringValue("/")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- data []byte
- expectedResult Functions
- expectErr bool
- }{
- // Success case, basic conditions.
- {case1Data, NewFunctions(func1, func2, func3, func4, func5, func6, func7), false},
- // Duplicate conditions, success case only one value is preserved.
- {case2Data, NewFunctions(func6), false},
- // empty condition error.
- {case3Data, nil, true},
- // Success case multiple keys, same condition.
- {case4Data, NewFunctions(func1, func2_1, func2_2, func2_3, func3, func4, func5, func6, func7), false},
- }
-
- for i, testCase := range testCases {
- result := new(Functions)
- err := json.Unmarshal(testCase.data, result)
- expectErr := (err != nil)
-
- if testCase.expectErr != expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if (*result).String() != testCase.expectedResult.String() {
- t.Fatalf("case %v: result: expected: %v, got: %v", i+1, testCase.expectedResult, *result)
- }
- }
- }
-}
diff --git a/pkg/bucket/policy/condition/ipaddressfunc.go b/pkg/bucket/policy/condition/ipaddressfunc.go
deleted file mode 100644
index 717c574ba..000000000
--- a/pkg/bucket/policy/condition/ipaddressfunc.go
+++ /dev/null
@@ -1,187 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "fmt"
- "net"
- "net/http"
- "sort"
-)
-
-func toIPAddressFuncString(n name, key Key, values []*net.IPNet) string {
- valueStrings := []string{}
- for _, value := range values {
- valueStrings = append(valueStrings, value.String())
- }
- sort.Strings(valueStrings)
-
- return fmt.Sprintf("%v:%v:%v", n, key, valueStrings)
-}
-
-// ipAddressFunc - IP address function. It checks whether value by Key in given
-// values is in IP network. Here Key must be AWSSourceIP.
-// For example,
-// - if values = [192.168.1.0/24], at evaluate() it returns whether IP address
-// in value map for AWSSourceIP falls in the network 192.168.1.10/24.
-type ipAddressFunc struct {
- k Key
- values []*net.IPNet
-}
-
-// evaluate() - evaluates to check whether IP address in values map for AWSSourceIP
-// falls in one of network or not.
-func (f ipAddressFunc) evaluate(values map[string][]string) bool {
- IPs := []net.IP{}
- requestValue, ok := values[http.CanonicalHeaderKey(f.k.Name())]
- if !ok {
- requestValue = values[f.k.Name()]
- }
-
- for _, s := range requestValue {
- IP := net.ParseIP(s)
- if IP == nil {
- panic(fmt.Errorf("invalid IP address '%v'", s))
- }
-
- IPs = append(IPs, IP)
- }
-
- for _, IP := range IPs {
- for _, IPNet := range f.values {
- if IPNet.Contains(IP) {
- return true
- }
- }
- }
-
- return false
-}
-
-// key() - returns condition key which is used by this condition function.
-// Key is always AWSSourceIP.
-func (f ipAddressFunc) key() Key {
- return f.k
-}
-
-// name() - returns "IpAddress" condition name.
-func (f ipAddressFunc) name() name {
- return ipAddress
-}
-
-func (f ipAddressFunc) String() string {
- return toIPAddressFuncString(ipAddress, f.k, f.values)
-}
-
-// toMap - returns map representation of this function.
-func (f ipAddressFunc) toMap() map[Key]ValueSet {
- if !f.k.IsValid() {
- return nil
- }
-
- values := NewValueSet()
- for _, value := range f.values {
- values.Add(NewStringValue(value.String()))
- }
-
- return map[Key]ValueSet{
- f.k: values,
- }
-}
-
-// notIPAddressFunc - Not IP address function. It checks whether value by Key in given
-// values is NOT in IP network. Here Key must be AWSSourceIP.
-// For example,
-// - if values = [192.168.1.0/24], at evaluate() it returns whether IP address
-// in value map for AWSSourceIP does not fall in the network 192.168.1.10/24.
-type notIPAddressFunc struct {
- ipAddressFunc
-}
-
-// evaluate() - evaluates to check whether IP address in values map for AWSSourceIP
-// does not fall in one of network.
-func (f notIPAddressFunc) evaluate(values map[string][]string) bool {
- return !f.ipAddressFunc.evaluate(values)
-}
-
-// name() - returns "NotIpAddress" condition name.
-func (f notIPAddressFunc) name() name {
- return notIPAddress
-}
-
-func (f notIPAddressFunc) String() string {
- return toIPAddressFuncString(notIPAddress, f.ipAddressFunc.k, f.ipAddressFunc.values)
-}
-
-func valuesToIPNets(n name, values ValueSet) ([]*net.IPNet, error) {
- IPNets := []*net.IPNet{}
- for v := range values {
- s, err := v.GetString()
- if err != nil {
- return nil, fmt.Errorf("value %v must be string representation of CIDR for %v condition", v, n)
- }
-
- var IPNet *net.IPNet
- _, IPNet, err = net.ParseCIDR(s)
- if err != nil {
- return nil, fmt.Errorf("value %v must be CIDR string for %v condition", s, n)
- }
-
- IPNets = append(IPNets, IPNet)
- }
-
- return IPNets, nil
-}
-
-// newIPAddressFunc - returns new IP address function.
-func newIPAddressFunc(key Key, values ValueSet) (Function, error) {
- IPNets, err := valuesToIPNets(ipAddress, values)
- if err != nil {
- return nil, err
- }
-
- return NewIPAddressFunc(key, IPNets...)
-}
-
-// NewIPAddressFunc - returns new IP address function.
-func NewIPAddressFunc(key Key, IPNets ...*net.IPNet) (Function, error) {
- if key != AWSSourceIP {
- return nil, fmt.Errorf("only %v key is allowed for %v condition", AWSSourceIP, ipAddress)
- }
-
- return &ipAddressFunc{key, IPNets}, nil
-}
-
-// newNotIPAddressFunc - returns new Not IP address function.
-func newNotIPAddressFunc(key Key, values ValueSet) (Function, error) {
- IPNets, err := valuesToIPNets(notIPAddress, values)
- if err != nil {
- return nil, err
- }
-
- return NewNotIPAddressFunc(key, IPNets...)
-}
-
-// NewNotIPAddressFunc - returns new Not IP address function.
-func NewNotIPAddressFunc(key Key, IPNets ...*net.IPNet) (Function, error) {
- if key != AWSSourceIP {
- return nil, fmt.Errorf("only %v key is allowed for %v condition", AWSSourceIP, notIPAddress)
- }
-
- return ¬IPAddressFunc{ipAddressFunc{key, IPNets}}, nil
-}
diff --git a/pkg/bucket/policy/condition/ipaddressfunc_test.go b/pkg/bucket/policy/condition/ipaddressfunc_test.go
deleted file mode 100644
index 5c0618304..000000000
--- a/pkg/bucket/policy/condition/ipaddressfunc_test.go
+++ /dev/null
@@ -1,279 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "reflect"
- "testing"
-)
-
-func TestIPAddressFuncEvaluate(t *testing.T) {
- case1Function, err := newIPAddressFunc(AWSSourceIP, NewValueSet(NewStringValue("192.168.1.0/24")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- function Function
- values map[string][]string
- expectedResult bool
- }{
- {case1Function, map[string][]string{"SourceIp": {"192.168.1.10"}}, true},
- {case1Function, map[string][]string{"SourceIp": {"192.168.2.10"}}, false},
- {case1Function, map[string][]string{}, false},
- {case1Function, map[string][]string{"delimiter": {"/"}}, false},
- }
-
- for i, testCase := range testCases {
- result := testCase.function.evaluate(testCase.values)
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestIPAddressFuncKey(t *testing.T) {
- case1Function, err := newIPAddressFunc(AWSSourceIP, NewValueSet(NewStringValue("192.168.1.0/24")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- function Function
- expectedResult Key
- }{
- {case1Function, AWSSourceIP},
- }
-
- for i, testCase := range testCases {
- result := testCase.function.key()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestIPAddressFuncToMap(t *testing.T) {
- case1Function, err := newIPAddressFunc(AWSSourceIP, NewValueSet(NewStringValue("192.168.1.0/24")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newIPAddressFunc(AWSSourceIP, NewValueSet(NewStringValue("192.168.1.0/24"), NewStringValue("10.1.10.1/32")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case1Result := map[Key]ValueSet{
- AWSSourceIP: NewValueSet(NewStringValue("192.168.1.0/24")),
- }
-
- case2Result := map[Key]ValueSet{
- AWSSourceIP: NewValueSet(NewStringValue("192.168.1.0/24"), NewStringValue("10.1.10.1/32")),
- }
-
- testCases := []struct {
- f Function
- expectedResult map[Key]ValueSet
- }{
- {case1Function, case1Result},
- {case2Function, case2Result},
- {&ipAddressFunc{}, nil},
- }
-
- for i, testCase := range testCases {
- result := testCase.f.toMap()
-
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestNotIPAddressFuncEvaluate(t *testing.T) {
- case1Function, err := newNotIPAddressFunc(AWSSourceIP, NewValueSet(NewStringValue("192.168.1.0/24")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- function Function
- values map[string][]string
- expectedResult bool
- }{
- {case1Function, map[string][]string{"SourceIp": {"192.168.2.10"}}, true},
- {case1Function, map[string][]string{}, true},
- {case1Function, map[string][]string{"delimiter": {"/"}}, true},
- {case1Function, map[string][]string{"SourceIp": {"192.168.1.10"}}, false},
- }
-
- for i, testCase := range testCases {
- result := testCase.function.evaluate(testCase.values)
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestNotIPAddressFuncKey(t *testing.T) {
- case1Function, err := newNotIPAddressFunc(AWSSourceIP, NewValueSet(NewStringValue("192.168.1.0/24")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- function Function
- expectedResult Key
- }{
- {case1Function, AWSSourceIP},
- }
-
- for i, testCase := range testCases {
- result := testCase.function.key()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestNotIPAddressFuncToMap(t *testing.T) {
- case1Function, err := newNotIPAddressFunc(AWSSourceIP, NewValueSet(NewStringValue("192.168.1.0/24")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newNotIPAddressFunc(AWSSourceIP, NewValueSet(NewStringValue("192.168.1.0/24"), NewStringValue("10.1.10.1/32")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case1Result := map[Key]ValueSet{
- AWSSourceIP: NewValueSet(NewStringValue("192.168.1.0/24")),
- }
-
- case2Result := map[Key]ValueSet{
- AWSSourceIP: NewValueSet(NewStringValue("192.168.1.0/24"), NewStringValue("10.1.10.1/32")),
- }
-
- testCases := []struct {
- f Function
- expectedResult map[Key]ValueSet
- }{
- {case1Function, case1Result},
- {case2Function, case2Result},
- {¬IPAddressFunc{}, nil},
- }
-
- for i, testCase := range testCases {
- result := testCase.f.toMap()
-
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestNewIPAddressFunc(t *testing.T) {
- case1Function, err := newIPAddressFunc(AWSSourceIP, NewValueSet(NewStringValue("192.168.1.0/24")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newIPAddressFunc(AWSSourceIP, NewValueSet(NewStringValue("192.168.1.0/24"), NewStringValue("10.1.10.1/32")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- key Key
- values ValueSet
- expectedResult Function
- expectErr bool
- }{
- {AWSSourceIP, NewValueSet(NewStringValue("192.168.1.0/24")), case1Function, false},
- {AWSSourceIP, NewValueSet(NewStringValue("192.168.1.0/24"), NewStringValue("10.1.10.1/32")), case2Function, false},
- // Unsupported key error.
- {S3Prefix, NewValueSet(NewStringValue("192.168.1.0/24")), nil, true},
- // Invalid value error.
- {AWSSourceIP, NewValueSet(NewStringValue("node1.example.org")), nil, true},
- // Invalid CIDR format error.
- {AWSSourceIP, NewValueSet(NewStringValue("192.168.1.0.0/24")), nil, true},
- }
-
- for i, testCase := range testCases {
- result, err := newIPAddressFunc(testCase.key, testCase.values)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if result.String() != testCase.expectedResult.String() {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
-
-func TestNewNotIPAddressFunc(t *testing.T) {
- case1Function, err := newNotIPAddressFunc(AWSSourceIP, NewValueSet(NewStringValue("192.168.1.0/24")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newNotIPAddressFunc(AWSSourceIP, NewValueSet(NewStringValue("192.168.1.0/24"), NewStringValue("10.1.10.1/32")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- key Key
- values ValueSet
- expectedResult Function
- expectErr bool
- }{
- {AWSSourceIP, NewValueSet(NewStringValue("192.168.1.0/24")), case1Function, false},
- {AWSSourceIP, NewValueSet(NewStringValue("192.168.1.0/24"), NewStringValue("10.1.10.1/32")), case2Function, false},
- // Unsupported key error.
- {S3Prefix, NewValueSet(NewStringValue("192.168.1.0/24")), nil, true},
- // Invalid value error.
- {AWSSourceIP, NewValueSet(NewStringValue("node1.example.org")), nil, true},
- // Invalid CIDR format error.
- {AWSSourceIP, NewValueSet(NewStringValue("192.168.1.0.0/24")), nil, true},
- }
-
- for i, testCase := range testCases {
- result, err := newNotIPAddressFunc(testCase.key, testCase.values)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if result.String() != testCase.expectedResult.String() {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
diff --git a/pkg/bucket/policy/condition/jwt.go b/pkg/bucket/policy/condition/jwt.go
deleted file mode 100644
index 3c8d223be..000000000
--- a/pkg/bucket/policy/condition/jwt.go
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-// JWT claims supported substitutions.
-// https://www.iana.org/assignments/jwt/jwt.xhtml#claims
-const (
- // JWTSub - JWT subject claim substitution.
- JWTSub Key = "jwt:sub"
-
- // JWTIss issuer claim substitution.
- JWTIss Key = "jwt:iss"
-
- // JWTAud audience claim substitution.
- JWTAud Key = "jwt:aud"
-
- // JWTJti JWT unique identifier claim substitution.
- JWTJti Key = "jwt:jti"
-
- JWTUpn Key = "jwt:upn"
- JWTName Key = "jwt:name"
- JWTGroups Key = "jwt:groups"
- JWTGivenName Key = "jwt:given_name"
- JWTFamilyName Key = "jwt:family_name"
- JWTMiddleName Key = "jwt:middle_name"
- JWTNickName Key = "jwt:nickname"
- JWTPrefUsername Key = "jwt:preferred_username"
- JWTProfile Key = "jwt:profile"
- JWTPicture Key = "jwt:picture"
- JWTWebsite Key = "jwt:website"
- JWTEmail Key = "jwt:email"
- JWTGender Key = "jwt:gender"
- JWTBirthdate Key = "jwt:birthdate"
- JWTPhoneNumber Key = "jwt:phone_number"
- JWTAddress Key = "jwt:address"
- JWTScope Key = "jwt:scope"
- JWTClientID Key = "jwt:client_id"
-)
-
-// JWTKeys - Supported JWT keys, non-exhaustive list please
-// expand as new claims are standardized.
-var JWTKeys = []Key{
- JWTSub,
- JWTIss,
- JWTAud,
- JWTJti,
- JWTName,
- JWTUpn,
- JWTGroups,
- JWTGivenName,
- JWTFamilyName,
- JWTMiddleName,
- JWTNickName,
- JWTPrefUsername,
- JWTProfile,
- JWTPicture,
- JWTWebsite,
- JWTEmail,
- JWTGender,
- JWTBirthdate,
- JWTPhoneNumber,
- JWTAddress,
- JWTScope,
- JWTClientID,
-}
diff --git a/pkg/bucket/policy/condition/key.go b/pkg/bucket/policy/condition/key.go
deleted file mode 100644
index 6550a74b4..000000000
--- a/pkg/bucket/policy/condition/key.go
+++ /dev/null
@@ -1,322 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "encoding/json"
- "fmt"
- "strings"
-)
-
-// Key - conditional key which is used to fetch values for any condition.
-// Refer https://docs.aws.amazon.com/IAM/latest/UserGuide/list_s3.html
-// for more information about available condition keys.
-type Key string
-
-const (
- // S3XAmzCopySource - key representing x-amz-copy-source HTTP header applicable to PutObject API only.
- S3XAmzCopySource Key = "s3:x-amz-copy-source"
-
- // S3XAmzServerSideEncryption - key representing x-amz-server-side-encryption HTTP header applicable
- // to PutObject API only.
- S3XAmzServerSideEncryption Key = "s3:x-amz-server-side-encryption"
-
- // S3XAmzServerSideEncryptionCustomerAlgorithm - key representing
- // x-amz-server-side-encryption-customer-algorithm HTTP header applicable to PutObject API only.
- S3XAmzServerSideEncryptionCustomerAlgorithm Key = "s3:x-amz-server-side-encryption-customer-algorithm"
-
- // S3XAmzMetadataDirective - key representing x-amz-metadata-directive HTTP header applicable to
- // PutObject API only.
- S3XAmzMetadataDirective Key = "s3:x-amz-metadata-directive"
-
- // S3XAmzContentSha256 - set a static content-sha256 for all calls for a given action.
- S3XAmzContentSha256 = "s3:x-amz-content-sha256"
-
- // S3XAmzStorageClass - key representing x-amz-storage-class HTTP header applicable to PutObject API
- // only.
- S3XAmzStorageClass Key = "s3:x-amz-storage-class"
-
- // S3LocationConstraint - key representing LocationConstraint XML tag of CreateBucket API only.
- S3LocationConstraint Key = "s3:LocationConstraint"
-
- // S3Prefix - key representing prefix query parameter of ListBucket API only.
- S3Prefix Key = "s3:prefix"
-
- // S3Delimiter - key representing delimiter query parameter of ListBucket API only.
- S3Delimiter Key = "s3:delimiter"
-
- // S3VersionID - Enables you to limit the permission for the
- // s3:PutObjectVersionTagging action to a specific object version.
- S3VersionID Key = "s3:versionid"
-
- // S3MaxKeys - key representing max-keys query parameter of ListBucket API only.
- S3MaxKeys Key = "s3:max-keys"
-
- // S3ObjectLockRemainingRetentionDays - key representing object-lock-remaining-retention-days
- // Enables enforcement of an object relative to the remaining retention days, you can set
- // minimum and maximum allowable retention periods for a bucket using a bucket policy.
- // This key are specific for s3:PutObjectRetention API.
- S3ObjectLockRemainingRetentionDays Key = "s3:object-lock-remaining-retention-days"
-
- // S3ObjectLockMode - key representing object-lock-mode
- // Enables enforcement of the specified object retention mode
- S3ObjectLockMode Key = "s3:object-lock-mode"
-
- // S3ObjectLockRetainUntilDate - key representing object-lock-retain-util-date
- // Enables enforcement of a specific retain-until-date
- S3ObjectLockRetainUntilDate Key = "s3:object-lock-retain-until-date"
-
- // S3ObjectLockLegalHold - key representing object-local-legal-hold
- // Enables enforcement of the specified object legal hold status
- S3ObjectLockLegalHold Key = "s3:object-lock-legal-hold"
-
- // AWSReferer - key representing Referer header of any API.
- AWSReferer Key = "aws:Referer"
-
- // AWSSourceIP - key representing client's IP address (not intermittent proxies) of any API.
- AWSSourceIP Key = "aws:SourceIp"
-
- // AWSUserAgent - key representing UserAgent header for any API.
- AWSUserAgent Key = "aws:UserAgent"
-
- // AWSSecureTransport - key representing if the clients request is authenticated or not.
- AWSSecureTransport Key = "aws:SecureTransport"
-
- // AWSCurrentTime - key representing the current time.
- AWSCurrentTime Key = "aws:CurrentTime"
-
- // AWSEpochTime - key representing the current epoch time.
- AWSEpochTime Key = "aws:EpochTime"
-
- // AWSPrincipalType - user principal type currently supported values are "User" and "Anonymous".
- AWSPrincipalType Key = "aws:principaltype"
-
- // AWSUserID - user unique ID, in MinIO this value is same as your user Access Key.
- AWSUserID Key = "aws:userid"
-
- // AWSUsername - user friendly name, in MinIO this value is same as your user Access Key.
- AWSUsername Key = "aws:username"
-
- // S3SignatureVersion - identifies the version of AWS Signature that you want to support for authenticated requests.
- S3SignatureVersion = "s3:signatureversion"
-
- // S3AuthType - optionally use this condition key to restrict incoming requests to use a specific authentication method.
- S3AuthType = "s3:authType"
-)
-
-// AllSupportedKeys - is list of all all supported keys.
-var AllSupportedKeys = append([]Key{
- S3SignatureVersion,
- S3AuthType,
- S3XAmzCopySource,
- S3XAmzServerSideEncryption,
- S3XAmzServerSideEncryptionCustomerAlgorithm,
- S3XAmzMetadataDirective,
- S3XAmzStorageClass,
- S3XAmzContentSha256,
- S3LocationConstraint,
- S3Prefix,
- S3Delimiter,
- S3MaxKeys,
- S3VersionID,
- S3ObjectLockRemainingRetentionDays,
- S3ObjectLockMode,
- S3ObjectLockLegalHold,
- S3ObjectLockRetainUntilDate,
- AWSReferer,
- AWSSourceIP,
- AWSUserAgent,
- AWSSecureTransport,
- AWSCurrentTime,
- AWSEpochTime,
- AWSPrincipalType,
- AWSUserID,
- AWSUsername,
- LDAPUser,
- LDAPUsername,
- // Add new supported condition keys.
-}, JWTKeys...)
-
-// CommonKeys - is list of all common condition keys.
-var CommonKeys = append([]Key{
- S3SignatureVersion,
- S3AuthType,
- S3XAmzContentSha256,
- S3LocationConstraint,
- AWSReferer,
- AWSSourceIP,
- AWSUserAgent,
- AWSSecureTransport,
- AWSCurrentTime,
- AWSEpochTime,
- AWSPrincipalType,
- AWSUserID,
- AWSUsername,
- LDAPUser,
- LDAPUsername,
-}, JWTKeys...)
-
-func substFuncFromValues(values map[string][]string) func(string) string {
- return func(v string) string {
- for _, key := range CommonKeys {
- // Empty values are not supported for policy variables.
- if rvalues, ok := values[key.Name()]; ok && rvalues[0] != "" {
- v = strings.Replace(v, key.VarName(), rvalues[0], -1)
- }
- }
- return v
- }
-}
-
-// IsValid - checks if key is valid or not.
-func (key Key) IsValid() bool {
- for _, supKey := range AllSupportedKeys {
- if supKey == key {
- return true
- }
- }
-
- return false
-}
-
-// MarshalJSON - encodes Key to JSON data.
-func (key Key) MarshalJSON() ([]byte, error) {
- if !key.IsValid() {
- return nil, fmt.Errorf("unknown key %v", key)
- }
-
- return json.Marshal(string(key))
-}
-
-// VarName - returns variable key name, such as "${aws:username}"
-func (key Key) VarName() string {
- return fmt.Sprintf("${%s}", key)
-}
-
-// Name - returns key name which is stripped value of prefixes "aws:" and "s3:"
-func (key Key) Name() string {
- keyString := string(key)
-
- if strings.HasPrefix(keyString, "aws:") {
- return strings.TrimPrefix(keyString, "aws:")
- } else if strings.HasPrefix(keyString, "jwt:") {
- return strings.TrimPrefix(keyString, "jwt:")
- } else if strings.HasPrefix(keyString, "ldap:") {
- return strings.TrimPrefix(keyString, "ldap:")
- }
- return strings.TrimPrefix(keyString, "s3:")
-}
-
-// UnmarshalJSON - decodes JSON data to Key.
-func (key *Key) UnmarshalJSON(data []byte) error {
- var s string
- if err := json.Unmarshal(data, &s); err != nil {
- return err
- }
-
- parsedKey, err := parseKey(s)
- if err != nil {
- return err
- }
-
- *key = parsedKey
- return nil
-}
-
-func parseKey(s string) (Key, error) {
- key := Key(s)
-
- if key.IsValid() {
- return key, nil
- }
-
- return key, fmt.Errorf("invalid condition key '%v'", s)
-}
-
-// KeySet - set representation of slice of keys.
-type KeySet map[Key]struct{}
-
-// Add - add a key to key set.
-func (set KeySet) Add(key Key) {
- set[key] = struct{}{}
-}
-
-// Merge merges two key sets, duplicates are overwritten
-func (set KeySet) Merge(mset KeySet) {
- for k, v := range mset {
- set[k] = v
- }
-}
-
-// Difference - returns a key set contains difference of two keys.
-// Example:
-// keySet1 := ["one", "two", "three"]
-// keySet2 := ["two", "four", "three"]
-// keySet1.Difference(keySet2) == ["one"]
-func (set KeySet) Difference(sset KeySet) KeySet {
- nset := make(KeySet)
-
- for k := range set {
- if _, ok := sset[k]; !ok {
- nset.Add(k)
- }
- }
-
- return nset
-}
-
-// IsEmpty - returns whether key set is empty or not.
-func (set KeySet) IsEmpty() bool {
- return len(set) == 0
-}
-
-func (set KeySet) String() string {
- return fmt.Sprintf("%v", set.ToSlice())
-}
-
-// ToSlice - returns slice of keys.
-func (set KeySet) ToSlice() []Key {
- keys := []Key{}
-
- for key := range set {
- keys = append(keys, key)
- }
-
- return keys
-}
-
-// NewKeySet - returns new KeySet contains given keys.
-func NewKeySet(keys ...Key) KeySet {
- set := make(KeySet)
- for _, key := range keys {
- set.Add(key)
- }
-
- return set
-}
-
-// AllSupportedAdminKeys - is list of all admin supported keys.
-var AllSupportedAdminKeys = []Key{
- AWSReferer,
- AWSSourceIP,
- AWSUserAgent,
- AWSSecureTransport,
- AWSCurrentTime,
- AWSEpochTime,
- // Add new supported condition keys.
-}
diff --git a/pkg/bucket/policy/condition/key_test.go b/pkg/bucket/policy/condition/key_test.go
deleted file mode 100644
index 7461532c8..000000000
--- a/pkg/bucket/policy/condition/key_test.go
+++ /dev/null
@@ -1,215 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "encoding/json"
- "reflect"
- "testing"
-)
-
-func TestKeyIsValid(t *testing.T) {
- testCases := []struct {
- key Key
- expectedResult bool
- }{
- {S3XAmzCopySource, true},
- {S3XAmzServerSideEncryption, true},
- {S3XAmzServerSideEncryptionCustomerAlgorithm, true},
- {S3XAmzMetadataDirective, true},
- {S3XAmzStorageClass, true},
- {S3LocationConstraint, true},
- {S3Prefix, true},
- {S3Delimiter, true},
- {S3MaxKeys, true},
- {AWSReferer, true},
- {AWSSourceIP, true},
- {Key("foo"), false},
- }
-
- for i, testCase := range testCases {
- result := testCase.key.IsValid()
-
- if testCase.expectedResult != result {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestKeyMarshalJSON(t *testing.T) {
- testCases := []struct {
- key Key
- expectedResult []byte
- expectErr bool
- }{
- {S3XAmzCopySource, []byte(`"s3:x-amz-copy-source"`), false},
- {Key("foo"), nil, true},
- }
-
- for i, testCase := range testCases {
- result, err := json.Marshal(testCase.key)
- expectErr := (err != nil)
-
- if testCase.expectErr != expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: key: expected: %v, got: %v\n", i+1, string(testCase.expectedResult), string(result))
- }
- }
- }
-}
-
-func TestKeyName(t *testing.T) {
- testCases := []struct {
- key Key
- expectedResult string
- }{
- {S3XAmzCopySource, "x-amz-copy-source"},
- {AWSReferer, "Referer"},
- }
-
- for i, testCase := range testCases {
- result := testCase.key.Name()
-
- if testCase.expectedResult != result {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestKeyUnmarshalJSON(t *testing.T) {
- testCases := []struct {
- data []byte
- expectedKey Key
- expectErr bool
- }{
- {[]byte(`"s3:x-amz-copy-source"`), S3XAmzCopySource, false},
- {[]byte(`"foo"`), Key(""), true},
- }
-
- for i, testCase := range testCases {
- var key Key
- err := json.Unmarshal(testCase.data, &key)
- expectErr := (err != nil)
-
- if testCase.expectErr != expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if testCase.expectedKey != key {
- t.Fatalf("case %v: key: expected: %v, got: %v\n", i+1, testCase.expectedKey, key)
- }
- }
- }
-}
-
-func TestKeySetAdd(t *testing.T) {
- testCases := []struct {
- set KeySet
- key Key
- expectedResult KeySet
- }{
- {NewKeySet(), S3XAmzCopySource, NewKeySet(S3XAmzCopySource)},
- {NewKeySet(S3XAmzCopySource), S3XAmzCopySource, NewKeySet(S3XAmzCopySource)},
- }
-
- for i, testCase := range testCases {
- testCase.set.Add(testCase.key)
-
- if !reflect.DeepEqual(testCase.expectedResult, testCase.set) {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, testCase.set)
- }
- }
-}
-
-func TestKeySetDifference(t *testing.T) {
- testCases := []struct {
- set KeySet
- setToDiff KeySet
- expectedResult KeySet
- }{
- {NewKeySet(), NewKeySet(S3XAmzCopySource), NewKeySet()},
- {NewKeySet(S3Prefix, S3Delimiter, S3MaxKeys), NewKeySet(S3Delimiter, S3MaxKeys), NewKeySet(S3Prefix)},
- }
-
- for i, testCase := range testCases {
- result := testCase.set.Difference(testCase.setToDiff)
-
- if !reflect.DeepEqual(testCase.expectedResult, result) {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestKeySetIsEmpty(t *testing.T) {
- testCases := []struct {
- set KeySet
- expectedResult bool
- }{
- {NewKeySet(), true},
- {NewKeySet(S3Delimiter), false},
- }
-
- for i, testCase := range testCases {
- result := testCase.set.IsEmpty()
-
- if testCase.expectedResult != result {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestKeySetString(t *testing.T) {
- testCases := []struct {
- set KeySet
- expectedResult string
- }{
- {NewKeySet(), `[]`},
- {NewKeySet(S3Delimiter), `[s3:delimiter]`},
- }
-
- for i, testCase := range testCases {
- result := testCase.set.String()
-
- if testCase.expectedResult != result {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestKeySetToSlice(t *testing.T) {
- testCases := []struct {
- set KeySet
- expectedResult []Key
- }{
- {NewKeySet(), []Key{}},
- {NewKeySet(S3Delimiter), []Key{S3Delimiter}},
- }
-
- for i, testCase := range testCases {
- result := testCase.set.ToSlice()
-
- if !reflect.DeepEqual(testCase.expectedResult, result) {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
diff --git a/pkg/bucket/policy/condition/ldap.go b/pkg/bucket/policy/condition/ldap.go
deleted file mode 100644
index 43f6eb30d..000000000
--- a/pkg/bucket/policy/condition/ldap.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-const (
- // LDAPUser - LDAP user DN, in MinIO this value is equal to user DN of the authenticated user.
- LDAPUser Key = "ldap:user"
-
- // LDAPUsername - LDAP username, in MinIO is the authenticated simply user.
- LDAPUsername Key = "ldap:username"
-)
diff --git a/pkg/bucket/policy/condition/name.go b/pkg/bucket/policy/condition/name.go
deleted file mode 100644
index 7ec24f25c..000000000
--- a/pkg/bucket/policy/condition/name.go
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "encoding/json"
- "fmt"
-)
-
-type name string
-
-const (
- stringEquals name = "StringEquals"
- stringNotEquals = "StringNotEquals"
- stringEqualsIgnoreCase = "StringEqualsIgnoreCase"
- stringNotEqualsIgnoreCase = "StringNotEqualsIgnoreCase"
- stringLike = "StringLike"
- stringNotLike = "StringNotLike"
- binaryEquals = "BinaryEquals"
- ipAddress = "IpAddress"
- notIPAddress = "NotIpAddress"
- null = "Null"
- boolean = "Bool"
- numericEquals = "NumericEquals"
- numericNotEquals = "NumericNotEquals"
- numericLessThan = "NumericLessThan"
- numericLessThanEquals = "NumericLessThanEquals"
- numericGreaterThan = "NumericGreaterThan"
- numericGreaterThanEquals = "NumericGreaterThanEquals"
- dateEquals = "DateEquals"
- dateNotEquals = "DateNotEquals"
- dateLessThan = "DateLessThan"
- dateLessThanEquals = "DateLessThanEquals"
- dateGreaterThan = "DateGreaterThan"
- dateGreaterThanEquals = "DateGreaterThanEquals"
-)
-
-var supportedConditions = []name{
- stringEquals,
- stringNotEquals,
- stringEqualsIgnoreCase,
- stringNotEqualsIgnoreCase,
- binaryEquals,
- stringLike,
- stringNotLike,
- ipAddress,
- notIPAddress,
- null,
- boolean,
- numericEquals,
- numericNotEquals,
- numericLessThan,
- numericLessThanEquals,
- numericGreaterThan,
- numericGreaterThanEquals,
- dateEquals,
- dateNotEquals,
- dateLessThan,
- dateLessThanEquals,
- dateGreaterThan,
- dateGreaterThanEquals,
- // Add new conditions here.
-}
-
-// IsValid - checks if name is valid or not.
-func (n name) IsValid() bool {
- for _, supn := range supportedConditions {
- if n == supn {
- return true
- }
- }
-
- return false
-}
-
-// MarshalJSON - encodes name to JSON data.
-func (n name) MarshalJSON() ([]byte, error) {
- if !n.IsValid() {
- return nil, fmt.Errorf("invalid name %v", n)
- }
-
- return json.Marshal(string(n))
-}
-
-// UnmarshalJSON - decodes JSON data to condition name.
-func (n *name) UnmarshalJSON(data []byte) error {
- var s string
- if err := json.Unmarshal(data, &s); err != nil {
- return err
- }
-
- parsedName, err := parseName(s)
- if err != nil {
- return err
- }
-
- *n = parsedName
- return nil
-}
-
-func parseName(s string) (name, error) {
- n := name(s)
-
- if n.IsValid() {
- return n, nil
- }
-
- return n, fmt.Errorf("invalid condition name '%v'", s)
-}
diff --git a/pkg/bucket/policy/condition/name_test.go b/pkg/bucket/policy/condition/name_test.go
deleted file mode 100644
index f42af0218..000000000
--- a/pkg/bucket/policy/condition/name_test.go
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "encoding/json"
- "reflect"
- "testing"
-)
-
-func TestNameIsValid(t *testing.T) {
- testCases := []struct {
- n name
- expectedResult bool
- }{
- {stringEquals, true},
- {stringNotEquals, true},
- {stringLike, true},
- {stringNotLike, true},
- {ipAddress, true},
- {notIPAddress, true},
- {null, true},
- {name("foo"), false},
- }
-
- for i, testCase := range testCases {
- result := testCase.n.IsValid()
-
- if testCase.expectedResult != result {
- t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestNameMarshalJSON(t *testing.T) {
- testCases := []struct {
- n name
- expectedResult []byte
- expectErr bool
- }{
- {stringEquals, []byte(`"StringEquals"`), false},
- {stringNotEquals, []byte(`"StringNotEquals"`), false},
- {stringLike, []byte(`"StringLike"`), false},
- {stringNotLike, []byte(`"StringNotLike"`), false},
- {ipAddress, []byte(`"IpAddress"`), false},
- {notIPAddress, []byte(`"NotIpAddress"`), false},
- {null, []byte(`"Null"`), false},
- {name("foo"), nil, true},
- }
-
- for i, testCase := range testCases {
- result, err := json.Marshal(testCase.n)
- expectErr := (err != nil)
-
- if testCase.expectErr != expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v", i+1, string(testCase.expectedResult), string(result))
- }
- }
- }
-}
-
-func TestNameUnmarshalJSON(t *testing.T) {
- testCases := []struct {
- data []byte
- expectedResult name
- expectErr bool
- }{
- {[]byte(`"StringEquals"`), stringEquals, false},
- {[]byte(`"foo"`), name(""), true},
- }
-
- for i, testCase := range testCases {
- var result name
- err := json.Unmarshal(testCase.data, &result)
- expectErr := (err != nil)
-
- if testCase.expectErr != expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if testCase.expectedResult != result {
- t.Fatalf("case %v: result: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
diff --git a/pkg/bucket/policy/condition/nullfunc.go b/pkg/bucket/policy/condition/nullfunc.go
deleted file mode 100644
index ecc789a9b..000000000
--- a/pkg/bucket/policy/condition/nullfunc.go
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "fmt"
- "net/http"
- "reflect"
- "strconv"
-)
-
-// nullFunc - Null condition function. It checks whether Key is not present in given
-// values or not.
-// For example,
-// 1. if Key = S3XAmzCopySource and Value = true, at evaluate() it returns whether
-// S3XAmzCopySource is NOT in given value map or not.
-// 2. if Key = S3XAmzCopySource and Value = false, at evaluate() it returns whether
-// S3XAmzCopySource is in given value map or not.
-// https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition_operators.html#Conditions_Null
-type nullFunc struct {
- k Key
- value bool
-}
-
-// evaluate() - evaluates to check whether Key is present in given values or not.
-// Depending on condition boolean value, this function returns true or false.
-func (f nullFunc) evaluate(values map[string][]string) bool {
- requestValue, ok := values[http.CanonicalHeaderKey(f.k.Name())]
- if !ok {
- requestValue = values[f.k.Name()]
- }
-
- if f.value {
- return len(requestValue) == 0
- }
-
- return len(requestValue) != 0
-}
-
-// key() - returns condition key which is used by this condition function.
-func (f nullFunc) key() Key {
- return f.k
-}
-
-// name() - returns "Null" condition name.
-func (f nullFunc) name() name {
- return null
-}
-
-func (f nullFunc) String() string {
- return fmt.Sprintf("%v:%v:%v", null, f.k, f.value)
-}
-
-// toMap - returns map representation of this function.
-func (f nullFunc) toMap() map[Key]ValueSet {
- if !f.k.IsValid() {
- return nil
- }
-
- return map[Key]ValueSet{
- f.k: NewValueSet(NewBoolValue(f.value)),
- }
-}
-
-func newNullFunc(key Key, values ValueSet) (Function, error) {
- if len(values) != 1 {
- return nil, fmt.Errorf("only one value is allowed for Null condition")
- }
-
- var value bool
- for v := range values {
- switch v.GetType() {
- case reflect.Bool:
- value, _ = v.GetBool()
- case reflect.String:
- var err error
- s, _ := v.GetString()
- if value, err = strconv.ParseBool(s); err != nil {
- return nil, fmt.Errorf("value must be a boolean string for Null condition")
- }
- default:
- return nil, fmt.Errorf("value must be a boolean for Null condition")
- }
- }
-
- return &nullFunc{key, value}, nil
-}
-
-// NewNullFunc - returns new Null function.
-func NewNullFunc(key Key, value bool) (Function, error) {
- return &nullFunc{key, value}, nil
-}
diff --git a/pkg/bucket/policy/condition/nullfunc_test.go b/pkg/bucket/policy/condition/nullfunc_test.go
deleted file mode 100644
index 1bca10a39..000000000
--- a/pkg/bucket/policy/condition/nullfunc_test.go
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "reflect"
- "testing"
-)
-
-func TestNullFuncEvaluate(t *testing.T) {
- case1Function, err := newNullFunc(S3Prefix, NewValueSet(NewBoolValue(true)))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newNullFunc(S3Prefix, NewValueSet(NewBoolValue(false)))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- function Function
- values map[string][]string
- expectedResult bool
- }{
- {case1Function, map[string][]string{"prefix": {"true"}}, false},
- {case1Function, map[string][]string{"prefix": {"false"}}, false},
- {case1Function, map[string][]string{"prefix": {"mybucket/foo"}}, false},
- {case1Function, map[string][]string{}, true},
- {case1Function, map[string][]string{"delimiter": {"/"}}, true},
- {case2Function, map[string][]string{"prefix": {"true"}}, true},
- {case2Function, map[string][]string{"prefix": {"false"}}, true},
- {case2Function, map[string][]string{"prefix": {"mybucket/foo"}}, true},
- {case2Function, map[string][]string{}, false},
- {case2Function, map[string][]string{"delimiter": {"/"}}, false},
- }
-
- for i, testCase := range testCases {
- result := testCase.function.evaluate(testCase.values)
-
- if result != testCase.expectedResult {
- t.Errorf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestNullFuncKey(t *testing.T) {
- case1Function, err := newNullFunc(S3XAmzCopySource, NewValueSet(NewBoolValue(true)))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- function Function
- expectedResult Key
- }{
- {case1Function, S3XAmzCopySource},
- }
-
- for i, testCase := range testCases {
- result := testCase.function.key()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestNullFuncToMap(t *testing.T) {
- case1Function, err := newNullFunc(S3Prefix, NewValueSet(NewBoolValue(true)))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case1Result := map[Key]ValueSet{
- S3Prefix: NewValueSet(NewBoolValue(true)),
- }
-
- case2Function, err := newNullFunc(S3Prefix, NewValueSet(NewBoolValue(false)))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Result := map[Key]ValueSet{
- S3Prefix: NewValueSet(NewBoolValue(false)),
- }
-
- testCases := []struct {
- f Function
- expectedResult map[Key]ValueSet
- }{
- {case1Function, case1Result},
- {case2Function, case2Result},
- {&nullFunc{}, nil},
- }
-
- for i, testCase := range testCases {
- result := testCase.f.toMap()
-
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestNewNullFunc(t *testing.T) {
- case1Function, err := newNullFunc(S3Prefix, NewValueSet(NewBoolValue(true)))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newNullFunc(S3Prefix, NewValueSet(NewBoolValue(false)))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- key Key
- values ValueSet
- expectedResult Function
- expectErr bool
- }{
- {S3Prefix, NewValueSet(NewBoolValue(true)), case1Function, false},
- {S3Prefix, NewValueSet(NewStringValue("false")), case2Function, false},
- // Multiple values error.
- {S3Prefix, NewValueSet(NewBoolValue(true), NewBoolValue(false)), nil, true},
- // Invalid boolean string error.
- {S3Prefix, NewValueSet(NewStringValue("foo")), nil, true},
- // Invalid value error.
- {S3Prefix, NewValueSet(NewIntValue(7)), nil, true},
- }
-
- for i, testCase := range testCases {
- result, err := newNullFunc(testCase.key, testCase.values)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
diff --git a/pkg/bucket/policy/condition/numericequalsfunc.go b/pkg/bucket/policy/condition/numericequalsfunc.go
deleted file mode 100644
index 7b43bc15f..000000000
--- a/pkg/bucket/policy/condition/numericequalsfunc.go
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "fmt"
- "net/http"
- "reflect"
- "strconv"
-)
-
-func toNumericEqualsFuncString(n name, key Key, value int) string {
- return fmt.Sprintf("%v:%v:%v", n, key, value)
-}
-
-// numericEqualsFunc - String equals function. It checks whether value by Key in given
-// values map is in condition values.
-// For example,
-// - if values = ["mybucket/foo"], at evaluate() it returns whether string
-// in value map for Key is in values.
-type numericEqualsFunc struct {
- k Key
- value int
-}
-
-// evaluate() - evaluates to check whether value by Key in given values is in
-// condition values.
-func (f numericEqualsFunc) evaluate(values map[string][]string) bool {
- requestValue, ok := values[http.CanonicalHeaderKey(f.k.Name())]
- if !ok {
- requestValue = values[f.k.Name()]
- }
-
- if len(requestValue) == 0 {
- return false
- }
-
- rvInt, err := strconv.Atoi(requestValue[0])
- if err != nil {
- return false
- }
-
- return f.value == rvInt
-}
-
-// key() - returns condition key which is used by this condition function.
-func (f numericEqualsFunc) key() Key {
- return f.k
-}
-
-// name() - returns "NumericEquals" condition name.
-func (f numericEqualsFunc) name() name {
- return numericEquals
-}
-
-func (f numericEqualsFunc) String() string {
- return toNumericEqualsFuncString(numericEquals, f.k, f.value)
-}
-
-// toMap - returns map representation of this function.
-func (f numericEqualsFunc) toMap() map[Key]ValueSet {
- if !f.k.IsValid() {
- return nil
- }
-
- values := NewValueSet()
- values.Add(NewIntValue(f.value))
-
- return map[Key]ValueSet{
- f.k: values,
- }
-}
-
-// numericNotEqualsFunc - String not equals function. It checks whether value by Key in
-// given values is NOT in condition values.
-// For example,
-// - if values = ["mybucket/foo"], at evaluate() it returns whether string
-// in value map for Key is NOT in values.
-type numericNotEqualsFunc struct {
- numericEqualsFunc
-}
-
-// evaluate() - evaluates to check whether value by Key in given values is NOT in
-// condition values.
-func (f numericNotEqualsFunc) evaluate(values map[string][]string) bool {
- return !f.numericEqualsFunc.evaluate(values)
-}
-
-// name() - returns "NumericNotEquals" condition name.
-func (f numericNotEqualsFunc) name() name {
- return numericNotEquals
-}
-
-func (f numericNotEqualsFunc) String() string {
- return toNumericEqualsFuncString(numericNotEquals, f.numericEqualsFunc.k, f.numericEqualsFunc.value)
-}
-
-func valueToInt(n name, values ValueSet) (v int, err error) {
- if len(values) != 1 {
- return -1, fmt.Errorf("only one value is allowed for %s condition", n)
- }
-
- for vs := range values {
- switch vs.GetType() {
- case reflect.Int:
- if v, err = vs.GetInt(); err != nil {
- return -1, err
- }
- case reflect.String:
- s, err := vs.GetString()
- if err != nil {
- return -1, err
- }
- if v, err = strconv.Atoi(s); err != nil {
- return -1, fmt.Errorf("value %s must be a int for %s condition: %w", vs, n, err)
- }
- default:
- return -1, fmt.Errorf("value %s must be a int for %s condition", vs, n)
- }
- }
-
- return v, nil
-
-}
-
-// newNumericEqualsFunc - returns new NumericEquals function.
-func newNumericEqualsFunc(key Key, values ValueSet) (Function, error) {
- v, err := valueToInt(numericEquals, values)
- if err != nil {
- return nil, err
- }
-
- return NewNumericEqualsFunc(key, v)
-}
-
-// NewNumericEqualsFunc - returns new NumericEquals function.
-func NewNumericEqualsFunc(key Key, value int) (Function, error) {
- return &numericEqualsFunc{key, value}, nil
-}
-
-// newNumericNotEqualsFunc - returns new NumericNotEquals function.
-func newNumericNotEqualsFunc(key Key, values ValueSet) (Function, error) {
- v, err := valueToInt(numericNotEquals, values)
- if err != nil {
- return nil, err
- }
-
- return NewNumericNotEqualsFunc(key, v)
-}
-
-// NewNumericNotEqualsFunc - returns new NumericNotEquals function.
-func NewNumericNotEqualsFunc(key Key, value int) (Function, error) {
- return &numericNotEqualsFunc{numericEqualsFunc{key, value}}, nil
-}
diff --git a/pkg/bucket/policy/condition/numericgreaterfunc.go b/pkg/bucket/policy/condition/numericgreaterfunc.go
deleted file mode 100644
index 9c3b558de..000000000
--- a/pkg/bucket/policy/condition/numericgreaterfunc.go
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "fmt"
- "net/http"
- "strconv"
-)
-
-func toNumericGreaterThanFuncString(n name, key Key, value int) string {
- return fmt.Sprintf("%v:%v:%v", n, key, value)
-}
-
-// numericGreaterThanFunc - String equals function. It checks whether value by Key in given
-// values map is in condition values.
-// For example,
-// - if values = ["mybucket/foo"], at evaluate() it returns whether string
-// in value map for Key is in values.
-type numericGreaterThanFunc struct {
- k Key
- value int
-}
-
-// evaluate() - evaluates to check whether value by Key in given values is in
-// condition values.
-func (f numericGreaterThanFunc) evaluate(values map[string][]string) bool {
- requestValue, ok := values[http.CanonicalHeaderKey(f.k.Name())]
- if !ok {
- requestValue = values[f.k.Name()]
- }
-
- if len(requestValue) == 0 {
- return false
- }
-
- rvInt, err := strconv.Atoi(requestValue[0])
- if err != nil {
- return false
- }
-
- return rvInt > f.value
-}
-
-// key() - returns condition key which is used by this condition function.
-func (f numericGreaterThanFunc) key() Key {
- return f.k
-}
-
-// name() - returns "NumericGreaterThan" condition name.
-func (f numericGreaterThanFunc) name() name {
- return numericGreaterThan
-}
-
-func (f numericGreaterThanFunc) String() string {
- return toNumericGreaterThanFuncString(numericGreaterThan, f.k, f.value)
-}
-
-// toMap - returns map representation of this function.
-func (f numericGreaterThanFunc) toMap() map[Key]ValueSet {
- if !f.k.IsValid() {
- return nil
- }
-
- values := NewValueSet()
- values.Add(NewIntValue(f.value))
-
- return map[Key]ValueSet{
- f.k: values,
- }
-}
-
-// numericGreaterThanEqualsFunc - String not equals function. It checks whether value by Key in
-// given values is NOT in condition values.
-// For example,
-// - if values = ["mybucket/foo"], at evaluate() it returns whether string
-// in value map for Key is NOT in values.
-type numericGreaterThanEqualsFunc struct {
- numericGreaterThanFunc
-}
-
-// evaluate() - evaluates to check whether value by Key in given values is NOT in
-// condition values.
-func (f numericGreaterThanEqualsFunc) evaluate(values map[string][]string) bool {
- requestValue, ok := values[http.CanonicalHeaderKey(f.k.Name())]
- if !ok {
- requestValue = values[f.k.Name()]
- }
-
- if len(requestValue) == 0 {
- return false
- }
-
- rvInt, err := strconv.Atoi(requestValue[0])
- if err != nil {
- return false
- }
-
- return rvInt >= f.value
-}
-
-// name() - returns "NumericGreaterThanEquals" condition name.
-func (f numericGreaterThanEqualsFunc) name() name {
- return numericGreaterThanEquals
-}
-
-func (f numericGreaterThanEqualsFunc) String() string {
- return toNumericGreaterThanFuncString(numericGreaterThanEquals, f.numericGreaterThanFunc.k, f.numericGreaterThanFunc.value)
-}
-
-// newNumericGreaterThanFunc - returns new NumericGreaterThan function.
-func newNumericGreaterThanFunc(key Key, values ValueSet) (Function, error) {
- v, err := valueToInt(numericGreaterThan, values)
- if err != nil {
- return nil, err
- }
-
- return NewNumericGreaterThanFunc(key, v)
-}
-
-// NewNumericGreaterThanFunc - returns new NumericGreaterThan function.
-func NewNumericGreaterThanFunc(key Key, value int) (Function, error) {
- return &numericGreaterThanFunc{key, value}, nil
-}
-
-// newNumericGreaterThanEqualsFunc - returns new NumericGreaterThanEquals function.
-func newNumericGreaterThanEqualsFunc(key Key, values ValueSet) (Function, error) {
- v, err := valueToInt(numericGreaterThanEquals, values)
- if err != nil {
- return nil, err
- }
-
- return NewNumericGreaterThanEqualsFunc(key, v)
-}
-
-// NewNumericGreaterThanEqualsFunc - returns new NumericGreaterThanEquals function.
-func NewNumericGreaterThanEqualsFunc(key Key, value int) (Function, error) {
- return &numericGreaterThanEqualsFunc{numericGreaterThanFunc{key, value}}, nil
-}
diff --git a/pkg/bucket/policy/condition/numericlessfunc.go b/pkg/bucket/policy/condition/numericlessfunc.go
deleted file mode 100644
index 805d9e33a..000000000
--- a/pkg/bucket/policy/condition/numericlessfunc.go
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "fmt"
- "net/http"
- "strconv"
-)
-
-func toNumericLessThanFuncString(n name, key Key, value int) string {
- return fmt.Sprintf("%v:%v:%v", n, key, value)
-}
-
-// numericLessThanFunc - String equals function. It checks whether value by Key in given
-// values map is in condition values.
-// For example,
-// - if values = ["mybucket/foo"], at evaluate() it returns whether string
-// in value map for Key is in values.
-type numericLessThanFunc struct {
- k Key
- value int
-}
-
-// evaluate() - evaluates to check whether value by Key in given values is in
-// condition values.
-func (f numericLessThanFunc) evaluate(values map[string][]string) bool {
- requestValue, ok := values[http.CanonicalHeaderKey(f.k.Name())]
- if !ok {
- requestValue = values[f.k.Name()]
- }
-
- if len(requestValue) == 0 {
- return false
- }
-
- rvInt, err := strconv.Atoi(requestValue[0])
- if err != nil {
- return false
- }
-
- return rvInt < f.value
-}
-
-// key() - returns condition key which is used by this condition function.
-func (f numericLessThanFunc) key() Key {
- return f.k
-}
-
-// name() - returns "NumericLessThan" condition name.
-func (f numericLessThanFunc) name() name {
- return numericLessThan
-}
-
-func (f numericLessThanFunc) String() string {
- return toNumericLessThanFuncString(numericLessThan, f.k, f.value)
-}
-
-// toMap - returns map representation of this function.
-func (f numericLessThanFunc) toMap() map[Key]ValueSet {
- if !f.k.IsValid() {
- return nil
- }
-
- values := NewValueSet()
- values.Add(NewIntValue(f.value))
-
- return map[Key]ValueSet{
- f.k: values,
- }
-}
-
-// numericLessThanEqualsFunc - String not equals function. It checks whether value by Key in
-// given values is NOT in condition values.
-// For example,
-// - if values = ["mybucket/foo"], at evaluate() it returns whether string
-// in value map for Key is NOT in values.
-type numericLessThanEqualsFunc struct {
- numericLessThanFunc
-}
-
-// evaluate() - evaluates to check whether value by Key in given values is NOT in
-// condition values.
-func (f numericLessThanEqualsFunc) evaluate(values map[string][]string) bool {
- requestValue, ok := values[http.CanonicalHeaderKey(f.k.Name())]
- if !ok {
- requestValue = values[f.k.Name()]
- }
-
- if len(requestValue) == 0 {
- return false
- }
-
- rvInt, err := strconv.Atoi(requestValue[0])
- if err != nil {
- return false
- }
-
- return rvInt <= f.value
-}
-
-// name() - returns "NumericLessThanEquals" condition name.
-func (f numericLessThanEqualsFunc) name() name {
- return numericLessThanEquals
-}
-
-func (f numericLessThanEqualsFunc) String() string {
- return toNumericLessThanFuncString(numericLessThanEquals, f.numericLessThanFunc.k, f.numericLessThanFunc.value)
-}
-
-// newNumericLessThanFunc - returns new NumericLessThan function.
-func newNumericLessThanFunc(key Key, values ValueSet) (Function, error) {
- v, err := valueToInt(numericLessThan, values)
- if err != nil {
- return nil, err
- }
-
- return NewNumericLessThanFunc(key, v)
-}
-
-// NewNumericLessThanFunc - returns new NumericLessThan function.
-func NewNumericLessThanFunc(key Key, value int) (Function, error) {
- return &numericLessThanFunc{key, value}, nil
-}
-
-// newNumericLessThanEqualsFunc - returns new NumericLessThanEquals function.
-func newNumericLessThanEqualsFunc(key Key, values ValueSet) (Function, error) {
- v, err := valueToInt(numericLessThanEquals, values)
- if err != nil {
- return nil, err
- }
-
- return NewNumericLessThanEqualsFunc(key, v)
-}
-
-// NewNumericLessThanEqualsFunc - returns new NumericLessThanEquals function.
-func NewNumericLessThanEqualsFunc(key Key, value int) (Function, error) {
- return &numericLessThanEqualsFunc{numericLessThanFunc{key, value}}, nil
-}
diff --git a/pkg/bucket/policy/condition/stringequalsfunc.go b/pkg/bucket/policy/condition/stringequalsfunc.go
deleted file mode 100644
index e0f20d239..000000000
--- a/pkg/bucket/policy/condition/stringequalsfunc.go
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "fmt"
- "net/http"
- "sort"
-
- "github.com/minio/minio-go/v7/pkg/s3utils"
- "github.com/minio/minio-go/v7/pkg/set"
-)
-
-func toStringEqualsFuncString(n name, key Key, values set.StringSet) string {
- valueStrings := values.ToSlice()
- sort.Strings(valueStrings)
-
- return fmt.Sprintf("%v:%v:%v", n, key, valueStrings)
-}
-
-// stringEqualsFunc - String equals function. It checks whether value by Key in given
-// values map is in condition values.
-// For example,
-// - if values = ["mybucket/foo"], at evaluate() it returns whether string
-// in value map for Key is in values.
-type stringEqualsFunc struct {
- k Key
- values set.StringSet
-}
-
-// evaluate() - evaluates to check whether value by Key in given values is in
-// condition values.
-func (f stringEqualsFunc) evaluate(values map[string][]string) bool {
- requestValue, ok := values[http.CanonicalHeaderKey(f.k.Name())]
- if !ok {
- requestValue = values[f.k.Name()]
- }
-
- fvalues := f.values.ApplyFunc(substFuncFromValues(values))
- return !fvalues.Intersection(set.CreateStringSet(requestValue...)).IsEmpty()
-}
-
-// key() - returns condition key which is used by this condition function.
-func (f stringEqualsFunc) key() Key {
- return f.k
-}
-
-// name() - returns "StringEquals" condition name.
-func (f stringEqualsFunc) name() name {
- return stringEquals
-}
-
-func (f stringEqualsFunc) String() string {
- return toStringEqualsFuncString(stringEquals, f.k, f.values)
-}
-
-// toMap - returns map representation of this function.
-func (f stringEqualsFunc) toMap() map[Key]ValueSet {
- if !f.k.IsValid() {
- return nil
- }
-
- values := NewValueSet()
- for _, value := range f.values.ToSlice() {
- values.Add(NewStringValue(value))
- }
-
- return map[Key]ValueSet{
- f.k: values,
- }
-}
-
-// stringNotEqualsFunc - String not equals function. It checks whether value by Key in
-// given values is NOT in condition values.
-// For example,
-// - if values = ["mybucket/foo"], at evaluate() it returns whether string
-// in value map for Key is NOT in values.
-type stringNotEqualsFunc struct {
- stringEqualsFunc
-}
-
-// evaluate() - evaluates to check whether value by Key in given values is NOT in
-// condition values.
-func (f stringNotEqualsFunc) evaluate(values map[string][]string) bool {
- return !f.stringEqualsFunc.evaluate(values)
-}
-
-// name() - returns "StringNotEquals" condition name.
-func (f stringNotEqualsFunc) name() name {
- return stringNotEquals
-}
-
-func (f stringNotEqualsFunc) String() string {
- return toStringEqualsFuncString(stringNotEquals, f.stringEqualsFunc.k, f.stringEqualsFunc.values)
-}
-
-func valuesToStringSlice(n name, values ValueSet) ([]string, error) {
- valueStrings := []string{}
-
- for value := range values {
- s, err := value.GetString()
- if err != nil {
- return nil, fmt.Errorf("value must be a string for %v condition", n)
- }
-
- valueStrings = append(valueStrings, s)
- }
-
- return valueStrings, nil
-}
-
-func validateStringEqualsValues(n name, key Key, values set.StringSet) error {
- for _, s := range values.ToSlice() {
- switch key {
- case S3XAmzCopySource:
- bucket, object := path2BucketAndObject(s)
- if object == "" {
- return fmt.Errorf("invalid value '%v' for '%v' for %v condition", s, S3XAmzCopySource, n)
- }
- if err := s3utils.CheckValidBucketName(bucket); err != nil {
- return err
- }
- case S3XAmzServerSideEncryption, S3XAmzServerSideEncryptionCustomerAlgorithm:
- if s != "AES256" {
- return fmt.Errorf("invalid value '%v' for '%v' for %v condition", s, S3XAmzServerSideEncryption, n)
- }
- case S3XAmzMetadataDirective:
- if s != "COPY" && s != "REPLACE" {
- return fmt.Errorf("invalid value '%v' for '%v' for %v condition", s, S3XAmzMetadataDirective, n)
- }
- case S3XAmzContentSha256:
- if s == "" {
- return fmt.Errorf("invalid empty value for '%v' for %v condition", S3XAmzContentSha256, n)
- }
- }
- }
-
- return nil
-}
-
-// newStringEqualsFunc - returns new StringEquals function.
-func newStringEqualsFunc(key Key, values ValueSet) (Function, error) {
- valueStrings, err := valuesToStringSlice(stringEquals, values)
- if err != nil {
- return nil, err
- }
-
- return NewStringEqualsFunc(key, valueStrings...)
-}
-
-// NewStringEqualsFunc - returns new StringEquals function.
-func NewStringEqualsFunc(key Key, values ...string) (Function, error) {
- sset := set.CreateStringSet(values...)
- if err := validateStringEqualsValues(stringEquals, key, sset); err != nil {
- return nil, err
- }
-
- return &stringEqualsFunc{key, sset}, nil
-}
-
-// newStringNotEqualsFunc - returns new StringNotEquals function.
-func newStringNotEqualsFunc(key Key, values ValueSet) (Function, error) {
- valueStrings, err := valuesToStringSlice(stringNotEquals, values)
- if err != nil {
- return nil, err
- }
-
- return NewStringNotEqualsFunc(key, valueStrings...)
-}
-
-// NewStringNotEqualsFunc - returns new StringNotEquals function.
-func NewStringNotEqualsFunc(key Key, values ...string) (Function, error) {
- sset := set.CreateStringSet(values...)
- if err := validateStringEqualsValues(stringNotEquals, key, sset); err != nil {
- return nil, err
- }
-
- return &stringNotEqualsFunc{stringEqualsFunc{key, sset}}, nil
-}
diff --git a/pkg/bucket/policy/condition/stringequalsfunc_test.go b/pkg/bucket/policy/condition/stringequalsfunc_test.go
deleted file mode 100644
index d0a92bea1..000000000
--- a/pkg/bucket/policy/condition/stringequalsfunc_test.go
+++ /dev/null
@@ -1,709 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "reflect"
- "testing"
-)
-
-func TestStringEqualsFuncEvaluate(t *testing.T) {
- case1Function, err := newStringEqualsFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newStringEqualsFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Function, err := newStringEqualsFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Function, err := newStringEqualsFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- function Function
- values map[string][]string
- expectedResult bool
- }{
- {case1Function, map[string][]string{"x-amz-copy-source": {"mybucket/myobject"}}, true},
- {case1Function, map[string][]string{"x-amz-copy-source": {"yourbucket/myobject"}}, false},
- {case1Function, map[string][]string{}, false},
- {case1Function, map[string][]string{"delimiter": {"/"}}, false},
-
- {case2Function, map[string][]string{"x-amz-server-side-encryption": {"AES256"}}, true},
- {case2Function, map[string][]string{}, false},
- {case2Function, map[string][]string{"delimiter": {"/"}}, false},
-
- {case3Function, map[string][]string{"x-amz-metadata-directive": {"REPLACE"}}, true},
- {case3Function, map[string][]string{"x-amz-metadata-directive": {"COPY"}}, false},
- {case3Function, map[string][]string{}, false},
- {case3Function, map[string][]string{"delimiter": {"/"}}, false},
-
- {case4Function, map[string][]string{"LocationConstraint": {"eu-west-1"}}, true},
- {case4Function, map[string][]string{"LocationConstraint": {"us-east-1"}}, false},
- {case4Function, map[string][]string{}, false},
- {case4Function, map[string][]string{"delimiter": {"/"}}, false},
- }
-
- for i, testCase := range testCases {
- result := testCase.function.evaluate(testCase.values)
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestStringEqualsFuncKey(t *testing.T) {
- case1Function, err := newStringEqualsFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newStringEqualsFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Function, err := newStringEqualsFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Function, err := newStringEqualsFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- function Function
- expectedResult Key
- }{
- {case1Function, S3XAmzCopySource},
- {case2Function, S3XAmzServerSideEncryption},
- {case3Function, S3XAmzMetadataDirective},
- {case4Function, S3LocationConstraint},
- }
-
- for i, testCase := range testCases {
- result := testCase.function.key()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestStringEqualsFuncToMap(t *testing.T) {
- case1Function, err := newStringEqualsFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case1Result := map[Key]ValueSet{
- S3XAmzCopySource: NewValueSet(NewStringValue("mybucket/myobject")),
- }
-
- case2Function, err := newStringEqualsFunc(S3XAmzCopySource,
- NewValueSet(
- NewStringValue("mybucket/myobject"),
- NewStringValue("yourbucket/myobject"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Result := map[Key]ValueSet{
- S3XAmzCopySource: NewValueSet(
- NewStringValue("mybucket/myobject"),
- NewStringValue("yourbucket/myobject"),
- ),
- }
-
- case3Function, err := newStringEqualsFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Result := map[Key]ValueSet{
- S3XAmzServerSideEncryption: NewValueSet(NewStringValue("AES256")),
- }
-
- case4Function, err := newStringEqualsFunc(S3XAmzServerSideEncryption,
- NewValueSet(
- NewStringValue("AES256"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Result := map[Key]ValueSet{
- S3XAmzServerSideEncryption: NewValueSet(
- NewStringValue("AES256"),
- ),
- }
-
- case5Function, err := newStringEqualsFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case5Result := map[Key]ValueSet{
- S3XAmzMetadataDirective: NewValueSet(NewStringValue("REPLACE")),
- }
-
- case6Function, err := newStringEqualsFunc(S3XAmzMetadataDirective,
- NewValueSet(
- NewStringValue("REPLACE"),
- NewStringValue("COPY"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case6Result := map[Key]ValueSet{
- S3XAmzMetadataDirective: NewValueSet(
- NewStringValue("REPLACE"),
- NewStringValue("COPY"),
- ),
- }
-
- case7Function, err := newStringEqualsFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case7Result := map[Key]ValueSet{
- S3LocationConstraint: NewValueSet(NewStringValue("eu-west-1")),
- }
-
- case8Function, err := newStringEqualsFunc(S3LocationConstraint,
- NewValueSet(
- NewStringValue("eu-west-1"),
- NewStringValue("us-west-1"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case8Result := map[Key]ValueSet{
- S3LocationConstraint: NewValueSet(
- NewStringValue("eu-west-1"),
- NewStringValue("us-west-1"),
- ),
- }
-
- testCases := []struct {
- f Function
- expectedResult map[Key]ValueSet
- }{
- {case1Function, case1Result},
- {case2Function, case2Result},
- {case3Function, case3Result},
- {case4Function, case4Result},
- {case5Function, case5Result},
- {case6Function, case6Result},
- {case7Function, case7Result},
- {case8Function, case8Result},
- {&stringEqualsFunc{}, nil},
- }
-
- for i, testCase := range testCases {
- result := testCase.f.toMap()
-
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestStringNotEqualsFuncEvaluate(t *testing.T) {
- case1Function, err := newStringNotEqualsFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newStringNotEqualsFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Function, err := newStringNotEqualsFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Function, err := newStringNotEqualsFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- function Function
- values map[string][]string
- expectedResult bool
- }{
- {case1Function, map[string][]string{"x-amz-copy-source": {"mybucket/myobject"}}, false},
- {case1Function, map[string][]string{"x-amz-copy-source": {"yourbucket/myobject"}}, true},
- {case1Function, map[string][]string{}, true},
- {case1Function, map[string][]string{"delimiter": {"/"}}, true},
-
- {case2Function, map[string][]string{"x-amz-server-side-encryption": {"AES256"}}, false},
- {case2Function, map[string][]string{}, true},
- {case2Function, map[string][]string{"delimiter": {"/"}}, true},
-
- {case3Function, map[string][]string{"x-amz-metadata-directive": {"REPLACE"}}, false},
- {case3Function, map[string][]string{"x-amz-metadata-directive": {"COPY"}}, true},
- {case3Function, map[string][]string{}, true},
- {case3Function, map[string][]string{"delimiter": {"/"}}, true},
-
- {case4Function, map[string][]string{"LocationConstraint": {"eu-west-1"}}, false},
- {case4Function, map[string][]string{"LocationConstraint": {"us-east-1"}}, true},
- {case4Function, map[string][]string{}, true},
- {case4Function, map[string][]string{"delimiter": {"/"}}, true},
- }
-
- for i, testCase := range testCases {
- result := testCase.function.evaluate(testCase.values)
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestStringNotEqualsFuncKey(t *testing.T) {
- case1Function, err := newStringNotEqualsFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newStringNotEqualsFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Function, err := newStringNotEqualsFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Function, err := newStringNotEqualsFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- function Function
- expectedResult Key
- }{
- {case1Function, S3XAmzCopySource},
- {case2Function, S3XAmzServerSideEncryption},
- {case3Function, S3XAmzMetadataDirective},
- {case4Function, S3LocationConstraint},
- }
-
- for i, testCase := range testCases {
- result := testCase.function.key()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestStringNotEqualsFuncToMap(t *testing.T) {
- case1Function, err := newStringNotEqualsFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case1Result := map[Key]ValueSet{
- S3XAmzCopySource: NewValueSet(NewStringValue("mybucket/myobject")),
- }
-
- case2Function, err := newStringNotEqualsFunc(S3XAmzCopySource,
- NewValueSet(
- NewStringValue("mybucket/myobject"),
- NewStringValue("yourbucket/myobject"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Result := map[Key]ValueSet{
- S3XAmzCopySource: NewValueSet(
- NewStringValue("mybucket/myobject"),
- NewStringValue("yourbucket/myobject"),
- ),
- }
-
- case3Function, err := newStringNotEqualsFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Result := map[Key]ValueSet{
- S3XAmzServerSideEncryption: NewValueSet(NewStringValue("AES256")),
- }
-
- case4Function, err := newStringNotEqualsFunc(S3XAmzServerSideEncryption,
- NewValueSet(
- NewStringValue("AES256"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Result := map[Key]ValueSet{
- S3XAmzServerSideEncryption: NewValueSet(
- NewStringValue("AES256"),
- ),
- }
-
- case5Function, err := newStringNotEqualsFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case5Result := map[Key]ValueSet{
- S3XAmzMetadataDirective: NewValueSet(NewStringValue("REPLACE")),
- }
-
- case6Function, err := newStringNotEqualsFunc(S3XAmzMetadataDirective,
- NewValueSet(
- NewStringValue("REPLACE"),
- NewStringValue("COPY"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case6Result := map[Key]ValueSet{
- S3XAmzMetadataDirective: NewValueSet(
- NewStringValue("REPLACE"),
- NewStringValue("COPY"),
- ),
- }
-
- case7Function, err := newStringNotEqualsFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case7Result := map[Key]ValueSet{
- S3LocationConstraint: NewValueSet(NewStringValue("eu-west-1")),
- }
-
- case8Function, err := newStringNotEqualsFunc(S3LocationConstraint,
- NewValueSet(
- NewStringValue("eu-west-1"),
- NewStringValue("us-west-1"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case8Result := map[Key]ValueSet{
- S3LocationConstraint: NewValueSet(
- NewStringValue("eu-west-1"),
- NewStringValue("us-west-1"),
- ),
- }
-
- testCases := []struct {
- f Function
- expectedResult map[Key]ValueSet
- }{
- {case1Function, case1Result},
- {case2Function, case2Result},
- {case3Function, case3Result},
- {case4Function, case4Result},
- {case5Function, case5Result},
- {case6Function, case6Result},
- {case7Function, case7Result},
- {case8Function, case8Result},
- {&stringNotEqualsFunc{}, nil},
- }
-
- for i, testCase := range testCases {
- result := testCase.f.toMap()
-
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestNewStringEqualsFunc(t *testing.T) {
- case1Function, err := newStringEqualsFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newStringEqualsFunc(S3XAmzCopySource,
- NewValueSet(
- NewStringValue("mybucket/myobject"),
- NewStringValue("yourbucket/myobject"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Function, err := newStringEqualsFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Function, err := newStringEqualsFunc(S3XAmzServerSideEncryption,
- NewValueSet(
- NewStringValue("AES256"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case5Function, err := newStringEqualsFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case6Function, err := newStringEqualsFunc(S3XAmzMetadataDirective,
- NewValueSet(
- NewStringValue("REPLACE"),
- NewStringValue("COPY"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case7Function, err := newStringEqualsFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case8Function, err := newStringEqualsFunc(S3LocationConstraint,
- NewValueSet(
- NewStringValue("eu-west-1"),
- NewStringValue("us-west-1"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- key Key
- values ValueSet
- expectedResult Function
- expectErr bool
- }{
- {S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")), case1Function, false},
- {S3XAmzCopySource,
- NewValueSet(
- NewStringValue("mybucket/myobject"),
- NewStringValue("yourbucket/myobject"),
- ), case2Function, false},
-
- {S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")), case3Function, false},
- {S3XAmzServerSideEncryption,
- NewValueSet(
- NewStringValue("AES256"),
- ), case4Function, false},
-
- {S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")), case5Function, false},
- {S3XAmzMetadataDirective,
- NewValueSet(
- NewStringValue("REPLACE"),
- NewStringValue("COPY"),
- ), case6Function, false},
-
- {S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")), case7Function, false},
- {S3LocationConstraint,
- NewValueSet(
- NewStringValue("eu-west-1"),
- NewStringValue("us-west-1"),
- ), case8Function, false},
-
- // Unsupported value error.
- {S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject"), NewIntValue(7)), nil, true},
- {S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256"), NewIntValue(7)), nil, true},
- {S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE"), NewIntValue(7)), nil, true},
- {S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1"), NewIntValue(7)), nil, true},
-
- // Invalid value error.
- {S3XAmzCopySource, NewValueSet(NewStringValue("mybucket")), nil, true},
- {S3XAmzServerSideEncryption, NewValueSet(NewStringValue("SSE-C")), nil, true},
- {S3XAmzMetadataDirective, NewValueSet(NewStringValue("DUPLICATE")), nil, true},
- }
-
- for i, testCase := range testCases {
- result, err := newStringEqualsFunc(testCase.key, testCase.values)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
-
-func TestNewStringNotEqualsFunc(t *testing.T) {
- case1Function, err := newStringNotEqualsFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newStringNotEqualsFunc(S3XAmzCopySource,
- NewValueSet(
- NewStringValue("mybucket/myobject"),
- NewStringValue("yourbucket/myobject"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Function, err := newStringNotEqualsFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Function, err := newStringNotEqualsFunc(S3XAmzServerSideEncryption,
- NewValueSet(
- NewStringValue("AES256"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case5Function, err := newStringNotEqualsFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case6Function, err := newStringNotEqualsFunc(S3XAmzMetadataDirective,
- NewValueSet(
- NewStringValue("REPLACE"),
- NewStringValue("COPY"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case7Function, err := newStringNotEqualsFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case8Function, err := newStringNotEqualsFunc(S3LocationConstraint,
- NewValueSet(
- NewStringValue("eu-west-1"),
- NewStringValue("us-west-1"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- key Key
- values ValueSet
- expectedResult Function
- expectErr bool
- }{
- {S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")), case1Function, false},
- {S3XAmzCopySource,
- NewValueSet(
- NewStringValue("mybucket/myobject"),
- NewStringValue("yourbucket/myobject"),
- ), case2Function, false},
-
- {S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")), case3Function, false},
- {S3XAmzServerSideEncryption,
- NewValueSet(
- NewStringValue("AES256"),
- ), case4Function, false},
-
- {S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")), case5Function, false},
- {S3XAmzMetadataDirective,
- NewValueSet(
- NewStringValue("REPLACE"),
- NewStringValue("COPY"),
- ), case6Function, false},
-
- {S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")), case7Function, false},
- {S3LocationConstraint,
- NewValueSet(
- NewStringValue("eu-west-1"),
- NewStringValue("us-west-1"),
- ), case8Function, false},
-
- // Unsupported value error.
- {S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject"), NewIntValue(7)), nil, true},
- {S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256"), NewIntValue(7)), nil, true},
- {S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE"), NewIntValue(7)), nil, true},
- {S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1"), NewIntValue(7)), nil, true},
-
- // Invalid value error.
- {S3XAmzCopySource, NewValueSet(NewStringValue("mybucket")), nil, true},
- {S3XAmzServerSideEncryption, NewValueSet(NewStringValue("SSE-C")), nil, true},
- {S3XAmzMetadataDirective, NewValueSet(NewStringValue("DUPLICATE")), nil, true},
- }
-
- for i, testCase := range testCases {
- result, err := newStringNotEqualsFunc(testCase.key, testCase.values)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
diff --git a/pkg/bucket/policy/condition/stringequalsignorecasefunc.go b/pkg/bucket/policy/condition/stringequalsignorecasefunc.go
deleted file mode 100644
index ecee11157..000000000
--- a/pkg/bucket/policy/condition/stringequalsignorecasefunc.go
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "fmt"
- "net/http"
- "sort"
- "strings"
-
- "github.com/minio/minio-go/v7/pkg/set"
-)
-
-func toStringEqualsIgnoreCaseFuncString(n name, key Key, values set.StringSet) string {
- valueStrings := values.ToSlice()
- sort.Strings(valueStrings)
-
- return fmt.Sprintf("%v:%v:%v", n, key, valueStrings)
-}
-
-// stringEqualsIgnoreCaseFunc - String equals function. It checks whether value by Key in given
-// values map is in condition values.
-// For example,
-// - if values = ["mybucket/foo"], at evaluate() it returns whether string
-// in value map for Key is in values.
-type stringEqualsIgnoreCaseFunc struct {
- k Key
- values set.StringSet
-}
-
-// evaluate() - evaluates to check whether value by Key in given values is in
-// condition values, ignores case.
-func (f stringEqualsIgnoreCaseFunc) evaluate(values map[string][]string) bool {
- requestValue, ok := values[http.CanonicalHeaderKey(f.k.Name())]
- if !ok {
- requestValue = values[f.k.Name()]
- }
-
- fvalues := f.values.ApplyFunc(substFuncFromValues(values))
-
- for _, v := range requestValue {
- if !fvalues.FuncMatch(strings.EqualFold, v).IsEmpty() {
- return true
- }
- }
-
- return false
-}
-
-// key() - returns condition key which is used by this condition function.
-func (f stringEqualsIgnoreCaseFunc) key() Key {
- return f.k
-}
-
-// name() - returns "StringEqualsIgnoreCase" condition name.
-func (f stringEqualsIgnoreCaseFunc) name() name {
- return stringEqualsIgnoreCase
-}
-
-func (f stringEqualsIgnoreCaseFunc) String() string {
- return toStringEqualsIgnoreCaseFuncString(stringEqualsIgnoreCase, f.k, f.values)
-}
-
-// toMap - returns map representation of this function.
-func (f stringEqualsIgnoreCaseFunc) toMap() map[Key]ValueSet {
- if !f.k.IsValid() {
- return nil
- }
-
- values := NewValueSet()
- for _, value := range f.values.ToSlice() {
- values.Add(NewStringValue(value))
- }
-
- return map[Key]ValueSet{
- f.k: values,
- }
-}
-
-// stringNotEqualsIgnoreCaseFunc - String not equals function. It checks whether value by Key in
-// given values is NOT in condition values.
-// For example,
-// - if values = ["mybucket/foo"], at evaluate() it returns whether string
-// in value map for Key is NOT in values.
-type stringNotEqualsIgnoreCaseFunc struct {
- stringEqualsIgnoreCaseFunc
-}
-
-// evaluate() - evaluates to check whether value by Key in given values is NOT in
-// condition values.
-func (f stringNotEqualsIgnoreCaseFunc) evaluate(values map[string][]string) bool {
- return !f.stringEqualsIgnoreCaseFunc.evaluate(values)
-}
-
-// name() - returns "StringNotEqualsIgnoreCase" condition name.
-func (f stringNotEqualsIgnoreCaseFunc) name() name {
- return stringNotEqualsIgnoreCase
-}
-
-func (f stringNotEqualsIgnoreCaseFunc) String() string {
- return toStringEqualsIgnoreCaseFuncString(stringNotEqualsIgnoreCase, f.stringEqualsIgnoreCaseFunc.k, f.stringEqualsIgnoreCaseFunc.values)
-}
-
-func validateStringEqualsIgnoreCaseValues(n name, key Key, values set.StringSet) error {
- return validateStringEqualsValues(n, key, values)
-}
-
-// newStringEqualsIgnoreCaseFunc - returns new StringEqualsIgnoreCase function.
-func newStringEqualsIgnoreCaseFunc(key Key, values ValueSet) (Function, error) {
- valueStrings, err := valuesToStringSlice(stringEqualsIgnoreCase, values)
- if err != nil {
- return nil, err
- }
-
- return NewStringEqualsIgnoreCaseFunc(key, valueStrings...)
-}
-
-// NewStringEqualsIgnoreCaseFunc - returns new StringEqualsIgnoreCase function.
-func NewStringEqualsIgnoreCaseFunc(key Key, values ...string) (Function, error) {
- sset := set.CreateStringSet(values...)
- if err := validateStringEqualsIgnoreCaseValues(stringEqualsIgnoreCase, key, sset); err != nil {
- return nil, err
- }
-
- return &stringEqualsIgnoreCaseFunc{key, sset}, nil
-}
-
-// newStringNotEqualsIgnoreCaseFunc - returns new StringNotEqualsIgnoreCase function.
-func newStringNotEqualsIgnoreCaseFunc(key Key, values ValueSet) (Function, error) {
- valueStrings, err := valuesToStringSlice(stringNotEqualsIgnoreCase, values)
- if err != nil {
- return nil, err
- }
-
- return NewStringNotEqualsIgnoreCaseFunc(key, valueStrings...)
-}
-
-// NewStringNotEqualsIgnoreCaseFunc - returns new StringNotEqualsIgnoreCase function.
-func NewStringNotEqualsIgnoreCaseFunc(key Key, values ...string) (Function, error) {
- sset := set.CreateStringSet(values...)
- if err := validateStringEqualsIgnoreCaseValues(stringNotEqualsIgnoreCase, key, sset); err != nil {
- return nil, err
- }
-
- return &stringNotEqualsIgnoreCaseFunc{stringEqualsIgnoreCaseFunc{key, sset}}, nil
-}
diff --git a/pkg/bucket/policy/condition/stringequalsignorecasefunc_test.go b/pkg/bucket/policy/condition/stringequalsignorecasefunc_test.go
deleted file mode 100644
index dde5d3cd6..000000000
--- a/pkg/bucket/policy/condition/stringequalsignorecasefunc_test.go
+++ /dev/null
@@ -1,711 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "reflect"
- "testing"
-)
-
-func TestStringEqualsIgnoreCaseFuncEvaluate(t *testing.T) {
- case1Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Function, err := newStringEqualsIgnoreCaseFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- function Function
- values map[string][]string
- expectedResult bool
- }{
- {case1Function, map[string][]string{"x-amz-copy-source": {"mybucket/myobject"}}, true},
- {case1Function, map[string][]string{"x-amz-copy-source": {"yourbucket/myobject"}}, false},
- {case1Function, map[string][]string{}, false},
- {case1Function, map[string][]string{"delimiter": {"/"}}, false},
-
- {case2Function, map[string][]string{"x-amz-server-side-encryption": {"AES256"}}, true},
- {case2Function, map[string][]string{"x-amz-server-side-encryption": {"aes256"}}, true},
- {case2Function, map[string][]string{}, false},
- {case2Function, map[string][]string{"delimiter": {"/"}}, false},
-
- {case3Function, map[string][]string{"x-amz-metadata-directive": {"REPLACE"}}, true},
- {case3Function, map[string][]string{"x-amz-metadata-directive": {"replace"}}, true},
- {case3Function, map[string][]string{"x-amz-metadata-directive": {"COPY"}}, false},
- {case3Function, map[string][]string{}, false},
- {case3Function, map[string][]string{"delimiter": {"/"}}, false},
-
- {case4Function, map[string][]string{"LocationConstraint": {"eu-west-1"}}, true},
- {case4Function, map[string][]string{"LocationConstraint": {"us-east-1"}}, false},
- {case4Function, map[string][]string{}, false},
- {case4Function, map[string][]string{"delimiter": {"/"}}, false},
- }
-
- for i, testCase := range testCases {
- result := testCase.function.evaluate(testCase.values)
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestStringEqualsIgnoreCaseFuncKey(t *testing.T) {
- case1Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Function, err := newStringEqualsIgnoreCaseFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- function Function
- expectedResult Key
- }{
- {case1Function, S3XAmzCopySource},
- {case2Function, S3XAmzServerSideEncryption},
- {case3Function, S3XAmzMetadataDirective},
- {case4Function, S3LocationConstraint},
- }
-
- for i, testCase := range testCases {
- result := testCase.function.key()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestStringEqualsIgnoreCaseFuncToMap(t *testing.T) {
- case1Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case1Result := map[Key]ValueSet{
- S3XAmzCopySource: NewValueSet(NewStringValue("mybucket/myobject")),
- }
-
- case2Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzCopySource,
- NewValueSet(
- NewStringValue("mybucket/myobject"),
- NewStringValue("yourbucket/myobject"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Result := map[Key]ValueSet{
- S3XAmzCopySource: NewValueSet(
- NewStringValue("mybucket/myobject"),
- NewStringValue("yourbucket/myobject"),
- ),
- }
-
- case3Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Result := map[Key]ValueSet{
- S3XAmzServerSideEncryption: NewValueSet(NewStringValue("AES256")),
- }
-
- case4Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzServerSideEncryption,
- NewValueSet(
- NewStringValue("AES256"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Result := map[Key]ValueSet{
- S3XAmzServerSideEncryption: NewValueSet(
- NewStringValue("AES256"),
- ),
- }
-
- case5Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case5Result := map[Key]ValueSet{
- S3XAmzMetadataDirective: NewValueSet(NewStringValue("REPLACE")),
- }
-
- case6Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzMetadataDirective,
- NewValueSet(
- NewStringValue("REPLACE"),
- NewStringValue("COPY"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case6Result := map[Key]ValueSet{
- S3XAmzMetadataDirective: NewValueSet(
- NewStringValue("REPLACE"),
- NewStringValue("COPY"),
- ),
- }
-
- case7Function, err := newStringEqualsIgnoreCaseFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case7Result := map[Key]ValueSet{
- S3LocationConstraint: NewValueSet(NewStringValue("eu-west-1")),
- }
-
- case8Function, err := newStringEqualsIgnoreCaseFunc(S3LocationConstraint,
- NewValueSet(
- NewStringValue("eu-west-1"),
- NewStringValue("us-west-1"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case8Result := map[Key]ValueSet{
- S3LocationConstraint: NewValueSet(
- NewStringValue("eu-west-1"),
- NewStringValue("us-west-1"),
- ),
- }
-
- testCases := []struct {
- f Function
- expectedResult map[Key]ValueSet
- }{
- {case1Function, case1Result},
- {case2Function, case2Result},
- {case3Function, case3Result},
- {case4Function, case4Result},
- {case5Function, case5Result},
- {case6Function, case6Result},
- {case7Function, case7Result},
- {case8Function, case8Result},
- {&stringEqualsFunc{}, nil},
- }
-
- for i, testCase := range testCases {
- result := testCase.f.toMap()
-
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestStringNotEqualsIgnoreCaseFuncEvaluate(t *testing.T) {
- case1Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Function, err := newStringNotEqualsIgnoreCaseFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- function Function
- values map[string][]string
- expectedResult bool
- }{
- {case1Function, map[string][]string{"x-amz-copy-source": {"mybucket/myobject"}}, false},
- {case1Function, map[string][]string{"x-amz-copy-source": {"yourbucket/myobject"}}, true},
- {case1Function, map[string][]string{}, true},
- {case1Function, map[string][]string{"delimiter": {"/"}}, true},
-
- {case2Function, map[string][]string{"x-amz-server-side-encryption": {"AES256"}}, false},
- {case2Function, map[string][]string{}, true},
- {case2Function, map[string][]string{"delimiter": {"/"}}, true},
-
- {case3Function, map[string][]string{"x-amz-metadata-directive": {"REPLACE"}}, false},
- {case3Function, map[string][]string{"x-amz-metadata-directive": {"COPY"}}, true},
- {case3Function, map[string][]string{}, true},
- {case3Function, map[string][]string{"delimiter": {"/"}}, true},
-
- {case4Function, map[string][]string{"LocationConstraint": {"eu-west-1"}}, false},
- {case4Function, map[string][]string{"LocationConstraint": {"us-east-1"}}, true},
- {case4Function, map[string][]string{}, true},
- {case4Function, map[string][]string{"delimiter": {"/"}}, true},
- }
-
- for i, testCase := range testCases {
- result := testCase.function.evaluate(testCase.values)
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestStringNotEqualsIgnoreCaseFuncKey(t *testing.T) {
- case1Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Function, err := newStringNotEqualsIgnoreCaseFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- function Function
- expectedResult Key
- }{
- {case1Function, S3XAmzCopySource},
- {case2Function, S3XAmzServerSideEncryption},
- {case3Function, S3XAmzMetadataDirective},
- {case4Function, S3LocationConstraint},
- }
-
- for i, testCase := range testCases {
- result := testCase.function.key()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestStringNotEqualsIgnoreCaseFuncToMap(t *testing.T) {
- case1Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case1Result := map[Key]ValueSet{
- S3XAmzCopySource: NewValueSet(NewStringValue("mybucket/myobject")),
- }
-
- case2Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzCopySource,
- NewValueSet(
- NewStringValue("mybucket/myobject"),
- NewStringValue("yourbucket/myobject"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Result := map[Key]ValueSet{
- S3XAmzCopySource: NewValueSet(
- NewStringValue("mybucket/myobject"),
- NewStringValue("yourbucket/myobject"),
- ),
- }
-
- case3Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Result := map[Key]ValueSet{
- S3XAmzServerSideEncryption: NewValueSet(NewStringValue("AES256")),
- }
-
- case4Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzServerSideEncryption,
- NewValueSet(
- NewStringValue("AES256"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Result := map[Key]ValueSet{
- S3XAmzServerSideEncryption: NewValueSet(
- NewStringValue("AES256"),
- ),
- }
-
- case5Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case5Result := map[Key]ValueSet{
- S3XAmzMetadataDirective: NewValueSet(NewStringValue("REPLACE")),
- }
-
- case6Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzMetadataDirective,
- NewValueSet(
- NewStringValue("REPLACE"),
- NewStringValue("COPY"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case6Result := map[Key]ValueSet{
- S3XAmzMetadataDirective: NewValueSet(
- NewStringValue("REPLACE"),
- NewStringValue("COPY"),
- ),
- }
-
- case7Function, err := newStringNotEqualsIgnoreCaseFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case7Result := map[Key]ValueSet{
- S3LocationConstraint: NewValueSet(NewStringValue("eu-west-1")),
- }
-
- case8Function, err := newStringNotEqualsIgnoreCaseFunc(S3LocationConstraint,
- NewValueSet(
- NewStringValue("eu-west-1"),
- NewStringValue("us-west-1"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case8Result := map[Key]ValueSet{
- S3LocationConstraint: NewValueSet(
- NewStringValue("eu-west-1"),
- NewStringValue("us-west-1"),
- ),
- }
-
- testCases := []struct {
- f Function
- expectedResult map[Key]ValueSet
- }{
- {case1Function, case1Result},
- {case2Function, case2Result},
- {case3Function, case3Result},
- {case4Function, case4Result},
- {case5Function, case5Result},
- {case6Function, case6Result},
- {case7Function, case7Result},
- {case8Function, case8Result},
- {&stringNotEqualsFunc{}, nil},
- }
-
- for i, testCase := range testCases {
- result := testCase.f.toMap()
-
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestNewStringEqualsIgnoreCaseFunc(t *testing.T) {
- case1Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzCopySource,
- NewValueSet(
- NewStringValue("mybucket/myobject"),
- NewStringValue("yourbucket/myobject"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzServerSideEncryption,
- NewValueSet(
- NewStringValue("AES256"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case5Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case6Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzMetadataDirective,
- NewValueSet(
- NewStringValue("REPLACE"),
- NewStringValue("COPY"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case7Function, err := newStringEqualsIgnoreCaseFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case8Function, err := newStringEqualsIgnoreCaseFunc(S3LocationConstraint,
- NewValueSet(
- NewStringValue("eu-west-1"),
- NewStringValue("us-west-1"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- key Key
- values ValueSet
- expectedResult Function
- expectErr bool
- }{
- {S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")), case1Function, false},
- {S3XAmzCopySource,
- NewValueSet(
- NewStringValue("mybucket/myobject"),
- NewStringValue("yourbucket/myobject"),
- ), case2Function, false},
-
- {S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")), case3Function, false},
- {S3XAmzServerSideEncryption,
- NewValueSet(
- NewStringValue("AES256"),
- ), case4Function, false},
-
- {S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")), case5Function, false},
- {S3XAmzMetadataDirective,
- NewValueSet(
- NewStringValue("REPLACE"),
- NewStringValue("COPY"),
- ), case6Function, false},
-
- {S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")), case7Function, false},
- {S3LocationConstraint,
- NewValueSet(
- NewStringValue("eu-west-1"),
- NewStringValue("us-west-1"),
- ), case8Function, false},
-
- // Unsupported value error.
- {S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject"), NewIntValue(7)), nil, true},
- {S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256"), NewIntValue(7)), nil, true},
- {S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE"), NewIntValue(7)), nil, true},
- {S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1"), NewIntValue(7)), nil, true},
-
- // Invalid value error.
- {S3XAmzCopySource, NewValueSet(NewStringValue("mybucket")), nil, true},
- {S3XAmzServerSideEncryption, NewValueSet(NewStringValue("SSE-C")), nil, true},
- {S3XAmzMetadataDirective, NewValueSet(NewStringValue("DUPLICATE")), nil, true},
- }
-
- for i, testCase := range testCases {
- result, err := newStringEqualsIgnoreCaseFunc(testCase.key, testCase.values)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
-
-func TestNewStringNotEqualsIgnoreCaseFunc(t *testing.T) {
- case1Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzCopySource,
- NewValueSet(
- NewStringValue("mybucket/myobject"),
- NewStringValue("yourbucket/myobject"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzServerSideEncryption,
- NewValueSet(
- NewStringValue("AES256"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case5Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case6Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzMetadataDirective,
- NewValueSet(
- NewStringValue("REPLACE"),
- NewStringValue("COPY"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case7Function, err := newStringNotEqualsIgnoreCaseFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case8Function, err := newStringNotEqualsIgnoreCaseFunc(S3LocationConstraint,
- NewValueSet(
- NewStringValue("eu-west-1"),
- NewStringValue("us-west-1"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- key Key
- values ValueSet
- expectedResult Function
- expectErr bool
- }{
- {S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")), case1Function, false},
- {S3XAmzCopySource,
- NewValueSet(
- NewStringValue("mybucket/myobject"),
- NewStringValue("yourbucket/myobject"),
- ), case2Function, false},
-
- {S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")), case3Function, false},
- {S3XAmzServerSideEncryption,
- NewValueSet(
- NewStringValue("AES256"),
- ), case4Function, false},
-
- {S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")), case5Function, false},
- {S3XAmzMetadataDirective,
- NewValueSet(
- NewStringValue("REPLACE"),
- NewStringValue("COPY"),
- ), case6Function, false},
-
- {S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")), case7Function, false},
- {S3LocationConstraint,
- NewValueSet(
- NewStringValue("eu-west-1"),
- NewStringValue("us-west-1"),
- ), case8Function, false},
-
- // Unsupported value error.
- {S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject"), NewIntValue(7)), nil, true},
- {S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256"), NewIntValue(7)), nil, true},
- {S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE"), NewIntValue(7)), nil, true},
- {S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1"), NewIntValue(7)), nil, true},
-
- // Invalid value error.
- {S3XAmzCopySource, NewValueSet(NewStringValue("mybucket")), nil, true},
- {S3XAmzServerSideEncryption, NewValueSet(NewStringValue("SSE-C")), nil, true},
- {S3XAmzMetadataDirective, NewValueSet(NewStringValue("DUPLICATE")), nil, true},
- }
-
- for i, testCase := range testCases {
- result, err := newStringNotEqualsIgnoreCaseFunc(testCase.key, testCase.values)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
diff --git a/pkg/bucket/policy/condition/stringlikefunc.go b/pkg/bucket/policy/condition/stringlikefunc.go
deleted file mode 100644
index 4d950c953..000000000
--- a/pkg/bucket/policy/condition/stringlikefunc.go
+++ /dev/null
@@ -1,175 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "fmt"
- "net/http"
- "sort"
-
- "github.com/minio/minio-go/v7/pkg/s3utils"
- "github.com/minio/minio-go/v7/pkg/set"
- "github.com/minio/pkg/wildcard"
-)
-
-func toStringLikeFuncString(n name, key Key, values set.StringSet) string {
- valueStrings := values.ToSlice()
- sort.Strings(valueStrings)
-
- return fmt.Sprintf("%v:%v:%v", n, key, valueStrings)
-}
-
-// stringLikeFunc - String like function. It checks whether value by Key in given
-// values map is widcard matching in condition values.
-// For example,
-// - if values = ["mybucket/foo*"], at evaluate() it returns whether string
-// in value map for Key is wildcard matching in values.
-type stringLikeFunc struct {
- k Key
- values set.StringSet
-}
-
-// evaluate() - evaluates to check whether value by Key in given values is wildcard
-// matching in condition values.
-func (f stringLikeFunc) evaluate(values map[string][]string) bool {
- requestValue, ok := values[http.CanonicalHeaderKey(f.k.Name())]
- if !ok {
- requestValue = values[f.k.Name()]
- }
-
- fvalues := f.values.ApplyFunc(substFuncFromValues(values))
-
- for _, v := range requestValue {
- if !fvalues.FuncMatch(wildcard.Match, v).IsEmpty() {
- return true
- }
- }
-
- return false
-}
-
-// key() - returns condition key which is used by this condition function.
-func (f stringLikeFunc) key() Key {
- return f.k
-}
-
-// name() - returns "StringLike" function name.
-func (f stringLikeFunc) name() name {
- return stringLike
-}
-
-func (f stringLikeFunc) String() string {
- return toStringLikeFuncString(stringLike, f.k, f.values)
-}
-
-// toMap - returns map representation of this function.
-func (f stringLikeFunc) toMap() map[Key]ValueSet {
- if !f.k.IsValid() {
- return nil
- }
-
- values := NewValueSet()
- for _, value := range f.values.ToSlice() {
- values.Add(NewStringValue(value))
- }
-
- return map[Key]ValueSet{
- f.k: values,
- }
-}
-
-// stringNotLikeFunc - String not like function. It checks whether value by Key in given
-// values map is NOT widcard matching in condition values.
-// For example,
-// - if values = ["mybucket/foo*"], at evaluate() it returns whether string
-// in value map for Key is NOT wildcard matching in values.
-type stringNotLikeFunc struct {
- stringLikeFunc
-}
-
-// evaluate() - evaluates to check whether value by Key in given values is NOT wildcard
-// matching in condition values.
-func (f stringNotLikeFunc) evaluate(values map[string][]string) bool {
- return !f.stringLikeFunc.evaluate(values)
-}
-
-// name() - returns "StringNotLike" function name.
-func (f stringNotLikeFunc) name() name {
- return stringNotLike
-}
-
-func (f stringNotLikeFunc) String() string {
- return toStringLikeFuncString(stringNotLike, f.stringLikeFunc.k, f.stringLikeFunc.values)
-}
-
-func validateStringLikeValues(n name, key Key, values set.StringSet) error {
- for _, s := range values.ToSlice() {
- switch key {
- case S3XAmzCopySource:
- bucket, object := path2BucketAndObject(s)
- if object == "" {
- return fmt.Errorf("invalid value '%v' for '%v' for %v condition", s, S3XAmzCopySource, n)
- }
- if err := s3utils.CheckValidBucketName(bucket); err != nil {
- return err
- }
- }
- }
-
- return nil
-}
-
-// newStringLikeFunc - returns new StringLike function.
-func newStringLikeFunc(key Key, values ValueSet) (Function, error) {
- valueStrings, err := valuesToStringSlice(stringLike, values)
- if err != nil {
- return nil, err
- }
-
- return NewStringLikeFunc(key, valueStrings...)
-}
-
-// NewStringLikeFunc - returns new StringLike function.
-func NewStringLikeFunc(key Key, values ...string) (Function, error) {
- sset := set.CreateStringSet(values...)
- if err := validateStringLikeValues(stringLike, key, sset); err != nil {
- return nil, err
- }
-
- return &stringLikeFunc{key, sset}, nil
-}
-
-// newStringNotLikeFunc - returns new StringNotLike function.
-func newStringNotLikeFunc(key Key, values ValueSet) (Function, error) {
- valueStrings, err := valuesToStringSlice(stringNotLike, values)
- if err != nil {
- return nil, err
- }
-
- return NewStringNotLikeFunc(key, valueStrings...)
-}
-
-// NewStringNotLikeFunc - returns new StringNotLike function.
-func NewStringNotLikeFunc(key Key, values ...string) (Function, error) {
- sset := set.CreateStringSet(values...)
- if err := validateStringLikeValues(stringNotLike, key, sset); err != nil {
- return nil, err
- }
-
- return &stringNotLikeFunc{stringLikeFunc{key, sset}}, nil
-}
diff --git a/pkg/bucket/policy/condition/stringlikefunc_test.go b/pkg/bucket/policy/condition/stringlikefunc_test.go
deleted file mode 100644
index e11413be3..000000000
--- a/pkg/bucket/policy/condition/stringlikefunc_test.go
+++ /dev/null
@@ -1,799 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "reflect"
- "testing"
-)
-
-func TestStringLikeFuncEvaluate(t *testing.T) {
- case1Function, err := newStringLikeFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newStringLikeFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Function, err := newStringLikeFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Function, err := newStringLikeFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case5Function, err := newStringLikeFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPL*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case6Function, err := newStringLikeFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case7Function, err := newStringLikeFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case8Function, err := newStringLikeFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- function Function
- values map[string][]string
- expectedResult bool
- }{
- {case1Function, map[string][]string{"x-amz-copy-source": {"mybucket/myobject"}}, true},
- {case1Function, map[string][]string{"x-amz-copy-source": {"mybucket/myobject.png"}}, true},
- {case1Function, map[string][]string{"x-amz-copy-source": {"yourbucket/myobject"}}, false},
- {case1Function, map[string][]string{}, false},
- {case1Function, map[string][]string{"delimiter": {"/"}}, false},
-
- {case2Function, map[string][]string{"x-amz-copy-source": {"mybucket/myobject"}}, true},
- {case2Function, map[string][]string{"x-amz-copy-source": {"mybucket/myobject.png"}}, false},
- {case2Function, map[string][]string{"x-amz-copy-source": {"yourbucket/myobject"}}, false},
- {case2Function, map[string][]string{}, false},
- {case2Function, map[string][]string{"delimiter": {"/"}}, false},
-
- {case3Function, map[string][]string{"x-amz-server-side-encryption": {"AES256"}}, true},
- {case3Function, map[string][]string{"x-amz-server-side-encryption": {"AES512"}}, true},
- {case3Function, map[string][]string{}, false},
- {case3Function, map[string][]string{"delimiter": {"/"}}, false},
-
- {case4Function, map[string][]string{"x-amz-server-side-encryption": {"AES256"}}, true},
- {case4Function, map[string][]string{"x-amz-server-side-encryption": {"AES512"}}, false},
- {case4Function, map[string][]string{}, false},
- {case4Function, map[string][]string{"delimiter": {"/"}}, false},
-
- {case5Function, map[string][]string{"x-amz-metadata-directive": {"REPLACE"}}, true},
- {case5Function, map[string][]string{"x-amz-metadata-directive": {"REPLACE/COPY"}}, true},
- {case5Function, map[string][]string{"x-amz-metadata-directive": {"COPY"}}, false},
- {case5Function, map[string][]string{}, false},
- {case5Function, map[string][]string{"delimiter": {"/"}}, false},
-
- {case6Function, map[string][]string{"x-amz-metadata-directive": {"REPLACE"}}, true},
- {case6Function, map[string][]string{"x-amz-metadata-directive": {"REPLACE/COPY"}}, false},
- {case6Function, map[string][]string{"x-amz-metadata-directive": {"COPY"}}, false},
- {case6Function, map[string][]string{}, false},
- {case6Function, map[string][]string{"delimiter": {"/"}}, false},
-
- {case7Function, map[string][]string{"LocationConstraint": {"eu-west-1"}}, true},
- {case7Function, map[string][]string{"LocationConstraint": {"eu-west-2"}}, true},
- {case7Function, map[string][]string{"LocationConstraint": {"us-east-1"}}, false},
- {case7Function, map[string][]string{}, false},
- {case7Function, map[string][]string{"delimiter": {"/"}}, false},
-
- {case8Function, map[string][]string{"LocationConstraint": {"eu-west-1"}}, true},
- {case8Function, map[string][]string{"LocationConstraint": {"eu-west-2"}}, false},
- {case8Function, map[string][]string{"LocationConstraint": {"us-east-1"}}, false},
- {case8Function, map[string][]string{}, false},
- {case8Function, map[string][]string{"delimiter": {"/"}}, false},
- }
-
- for i, testCase := range testCases {
- result := testCase.function.evaluate(testCase.values)
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestStringLikeFuncKey(t *testing.T) {
- case1Function, err := newStringLikeFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newStringLikeFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Function, err := newStringLikeFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Function, err := newStringLikeFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- function Function
- expectedResult Key
- }{
- {case1Function, S3XAmzCopySource},
- {case2Function, S3XAmzServerSideEncryption},
- {case3Function, S3XAmzMetadataDirective},
- {case4Function, S3LocationConstraint},
- }
-
- for i, testCase := range testCases {
- result := testCase.function.key()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestStringLikeFuncToMap(t *testing.T) {
- case1Function, err := newStringLikeFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case1Result := map[Key]ValueSet{
- S3XAmzCopySource: NewValueSet(NewStringValue("mybucket/*")),
- }
-
- case2Function, err := newStringLikeFunc(S3XAmzCopySource,
- NewValueSet(
- NewStringValue("mybucket/*"),
- NewStringValue("yourbucket/myobject*"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Result := map[Key]ValueSet{
- S3XAmzCopySource: NewValueSet(
- NewStringValue("mybucket/*"),
- NewStringValue("yourbucket/myobject*"),
- ),
- }
-
- case3Function, err := newStringLikeFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Result := map[Key]ValueSet{
- S3XAmzServerSideEncryption: NewValueSet(NewStringValue("AES*")),
- }
-
- case4Function, err := newStringLikeFunc(S3XAmzServerSideEncryption,
- NewValueSet(
- NewStringValue("AES*"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Result := map[Key]ValueSet{
- S3XAmzServerSideEncryption: NewValueSet(
- NewStringValue("AES*"),
- ),
- }
-
- case5Function, err := newStringLikeFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPL*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case5Result := map[Key]ValueSet{
- S3XAmzMetadataDirective: NewValueSet(NewStringValue("REPL*")),
- }
-
- case6Function, err := newStringLikeFunc(S3XAmzMetadataDirective,
- NewValueSet(
- NewStringValue("REPL*"),
- NewStringValue("COPY*"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case6Result := map[Key]ValueSet{
- S3XAmzMetadataDirective: NewValueSet(
- NewStringValue("REPL*"),
- NewStringValue("COPY*"),
- ),
- }
-
- case7Function, err := newStringLikeFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case7Result := map[Key]ValueSet{
- S3LocationConstraint: NewValueSet(NewStringValue("eu-west-*")),
- }
-
- case8Function, err := newStringLikeFunc(S3LocationConstraint,
- NewValueSet(
- NewStringValue("eu-west-*"),
- NewStringValue("us-west-*"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case8Result := map[Key]ValueSet{
- S3LocationConstraint: NewValueSet(
- NewStringValue("eu-west-*"),
- NewStringValue("us-west-*"),
- ),
- }
-
- testCases := []struct {
- f Function
- expectedResult map[Key]ValueSet
- }{
- {case1Function, case1Result},
- {case2Function, case2Result},
- {case3Function, case3Result},
- {case4Function, case4Result},
- {case5Function, case5Result},
- {case6Function, case6Result},
- {case7Function, case7Result},
- {case8Function, case8Result},
- {&stringLikeFunc{}, nil},
- }
-
- for i, testCase := range testCases {
- result := testCase.f.toMap()
-
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestStringNotLikeFuncEvaluate(t *testing.T) {
- case1Function, err := newStringNotLikeFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newStringNotLikeFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Function, err := newStringNotLikeFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Function, err := newStringNotLikeFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case5Function, err := newStringNotLikeFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPL*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case6Function, err := newStringNotLikeFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case7Function, err := newStringNotLikeFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case8Function, err := newStringNotLikeFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- function Function
- values map[string][]string
- expectedResult bool
- }{
- {case1Function, map[string][]string{"x-amz-copy-source": {"mybucket/myobject"}}, false},
- {case1Function, map[string][]string{"x-amz-copy-source": {"mybucket/myobject.png"}}, false},
- {case1Function, map[string][]string{"x-amz-copy-source": {"yourbucket/myobject"}}, true},
- {case1Function, map[string][]string{}, true},
- {case1Function, map[string][]string{"delimiter": {"/"}}, true},
-
- {case2Function, map[string][]string{"x-amz-copy-source": {"mybucket/myobject"}}, false},
- {case2Function, map[string][]string{"x-amz-copy-source": {"mybucket/myobject.png"}}, true},
- {case2Function, map[string][]string{"x-amz-copy-source": {"yourbucket/myobject"}}, true},
- {case2Function, map[string][]string{}, true},
- {case2Function, map[string][]string{"delimiter": {"/"}}, true},
-
- {case3Function, map[string][]string{"x-amz-server-side-encryption": {"AES256"}}, false},
- {case3Function, map[string][]string{"x-amz-server-side-encryption": {"AES512"}}, false},
- {case3Function, map[string][]string{}, true},
- {case3Function, map[string][]string{"delimiter": {"/"}}, true},
-
- {case4Function, map[string][]string{"x-amz-server-side-encryption": {"AES256"}}, false},
- {case4Function, map[string][]string{"x-amz-server-side-encryption": {"AES512"}}, true},
- {case4Function, map[string][]string{}, true},
- {case4Function, map[string][]string{"delimiter": {"/"}}, true},
-
- {case5Function, map[string][]string{"x-amz-metadata-directive": {"REPLACE"}}, false},
- {case5Function, map[string][]string{"x-amz-metadata-directive": {"REPLACE/COPY"}}, false},
- {case5Function, map[string][]string{"x-amz-metadata-directive": {"COPY"}}, true},
- {case5Function, map[string][]string{}, true},
- {case5Function, map[string][]string{"delimiter": {"/"}}, true},
-
- {case6Function, map[string][]string{"x-amz-metadata-directive": {"REPLACE"}}, false},
- {case6Function, map[string][]string{"x-amz-metadata-directive": {"REPLACE/COPY"}}, true},
- {case6Function, map[string][]string{"x-amz-metadata-directive": {"COPY"}}, true},
- {case6Function, map[string][]string{}, true},
- {case6Function, map[string][]string{"delimiter": {"/"}}, true},
-
- {case7Function, map[string][]string{"LocationConstraint": {"eu-west-1"}}, false},
- {case7Function, map[string][]string{"LocationConstraint": {"eu-west-2"}}, false},
- {case7Function, map[string][]string{"LocationConstraint": {"us-east-1"}}, true},
- {case7Function, map[string][]string{}, true},
- {case7Function, map[string][]string{"delimiter": {"/"}}, true},
-
- {case8Function, map[string][]string{"LocationConstraint": {"eu-west-1"}}, false},
- {case8Function, map[string][]string{"LocationConstraint": {"eu-west-2"}}, true},
- {case8Function, map[string][]string{"LocationConstraint": {"us-east-1"}}, true},
- {case8Function, map[string][]string{}, true},
- {case8Function, map[string][]string{"delimiter": {"/"}}, true},
- }
-
- for i, testCase := range testCases {
- result := testCase.function.evaluate(testCase.values)
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestStringNotLikeFuncKey(t *testing.T) {
- case1Function, err := newStringNotLikeFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newStringNotLikeFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Function, err := newStringNotLikeFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Function, err := newStringNotLikeFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- function Function
- expectedResult Key
- }{
- {case1Function, S3XAmzCopySource},
- {case2Function, S3XAmzServerSideEncryption},
- {case3Function, S3XAmzMetadataDirective},
- {case4Function, S3LocationConstraint},
- }
-
- for i, testCase := range testCases {
- result := testCase.function.key()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestStringNotLikeFuncToMap(t *testing.T) {
- case1Function, err := newStringNotLikeFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case1Result := map[Key]ValueSet{
- S3XAmzCopySource: NewValueSet(NewStringValue("mybucket/*")),
- }
-
- case2Function, err := newStringNotLikeFunc(S3XAmzCopySource,
- NewValueSet(
- NewStringValue("mybucket/*"),
- NewStringValue("yourbucket/myobject*"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Result := map[Key]ValueSet{
- S3XAmzCopySource: NewValueSet(
- NewStringValue("mybucket/*"),
- NewStringValue("yourbucket/myobject*"),
- ),
- }
-
- case3Function, err := newStringNotLikeFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Result := map[Key]ValueSet{
- S3XAmzServerSideEncryption: NewValueSet(NewStringValue("AES*")),
- }
-
- case4Function, err := newStringNotLikeFunc(S3XAmzServerSideEncryption,
- NewValueSet(
- NewStringValue("AES*"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Result := map[Key]ValueSet{
- S3XAmzServerSideEncryption: NewValueSet(
- NewStringValue("AES*"),
- ),
- }
-
- case5Function, err := newStringNotLikeFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPL*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case5Result := map[Key]ValueSet{
- S3XAmzMetadataDirective: NewValueSet(NewStringValue("REPL*")),
- }
-
- case6Function, err := newStringNotLikeFunc(S3XAmzMetadataDirective,
- NewValueSet(
- NewStringValue("REPL*"),
- NewStringValue("COPY*"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case6Result := map[Key]ValueSet{
- S3XAmzMetadataDirective: NewValueSet(
- NewStringValue("REPL*"),
- NewStringValue("COPY*"),
- ),
- }
-
- case7Function, err := newStringNotLikeFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case7Result := map[Key]ValueSet{
- S3LocationConstraint: NewValueSet(NewStringValue("eu-west-*")),
- }
-
- case8Function, err := newStringNotLikeFunc(S3LocationConstraint,
- NewValueSet(
- NewStringValue("eu-west-*"),
- NewStringValue("us-west-*"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case8Result := map[Key]ValueSet{
- S3LocationConstraint: NewValueSet(
- NewStringValue("eu-west-*"),
- NewStringValue("us-west-*"),
- ),
- }
-
- testCases := []struct {
- f Function
- expectedResult map[Key]ValueSet
- }{
- {case1Function, case1Result},
- {case2Function, case2Result},
- {case3Function, case3Result},
- {case4Function, case4Result},
- {case5Function, case5Result},
- {case6Function, case6Result},
- {case7Function, case7Result},
- {case8Function, case8Result},
- {&stringNotLikeFunc{}, nil},
- }
-
- for i, testCase := range testCases {
- result := testCase.f.toMap()
-
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestNewStringLikeFunc(t *testing.T) {
- case1Function, err := newStringLikeFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newStringLikeFunc(S3XAmzCopySource,
- NewValueSet(
- NewStringValue("mybucket/*"),
- NewStringValue("yourbucket/myobject*"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Function, err := newStringLikeFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Function, err := newStringLikeFunc(S3XAmzServerSideEncryption,
- NewValueSet(
- NewStringValue("AES*"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case5Function, err := newStringLikeFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPL*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case6Function, err := newStringLikeFunc(S3XAmzMetadataDirective,
- NewValueSet(
- NewStringValue("REPL*"),
- NewStringValue("COPY*"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case7Function, err := newStringLikeFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case8Function, err := newStringLikeFunc(S3LocationConstraint,
- NewValueSet(
- NewStringValue("eu-west-*"),
- NewStringValue("us-west-*"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- key Key
- values ValueSet
- expectedResult Function
- expectErr bool
- }{
- {S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/*")), case1Function, false},
- {S3XAmzCopySource,
- NewValueSet(
- NewStringValue("mybucket/*"),
- NewStringValue("yourbucket/myobject*"),
- ), case2Function, false},
-
- {S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES*")), case3Function, false},
- {S3XAmzServerSideEncryption,
- NewValueSet(
- NewStringValue("AES*"),
- ), case4Function, false},
-
- {S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPL*")), case5Function, false},
- {S3XAmzMetadataDirective,
- NewValueSet(
- NewStringValue("REPL*"),
- NewStringValue("COPY*"),
- ), case6Function, false},
-
- {S3LocationConstraint, NewValueSet(NewStringValue("eu-west-*")), case7Function, false},
- {S3LocationConstraint,
- NewValueSet(
- NewStringValue("eu-west-*"),
- NewStringValue("us-west-*"),
- ), case8Function, false},
-
- // Unsupported value error.
- {S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject"), NewIntValue(7)), nil, true},
- {S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256"), NewIntValue(7)), nil, true},
- {S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE"), NewIntValue(7)), nil, true},
- {S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1"), NewIntValue(7)), nil, true},
-
- // Invalid value error.
- {S3XAmzCopySource, NewValueSet(NewStringValue("mybucket")), nil, true},
- }
-
- for i, testCase := range testCases {
- result, err := newStringLikeFunc(testCase.key, testCase.values)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
-
-func TestNewStringNotLikeFunc(t *testing.T) {
- case1Function, err := newStringNotLikeFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Function, err := newStringNotLikeFunc(S3XAmzCopySource,
- NewValueSet(
- NewStringValue("mybucket/*"),
- NewStringValue("yourbucket/myobject*"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Function, err := newStringNotLikeFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Function, err := newStringNotLikeFunc(S3XAmzServerSideEncryption,
- NewValueSet(
- NewStringValue("AES*"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case5Function, err := newStringNotLikeFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPL*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case6Function, err := newStringNotLikeFunc(S3XAmzMetadataDirective,
- NewValueSet(
- NewStringValue("REPL*"),
- NewStringValue("COPY*"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case7Function, err := newStringNotLikeFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-*")))
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case8Function, err := newStringNotLikeFunc(S3LocationConstraint,
- NewValueSet(
- NewStringValue("eu-west-*"),
- NewStringValue("us-west-*"),
- ),
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- key Key
- values ValueSet
- expectedResult Function
- expectErr bool
- }{
- {S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/*")), case1Function, false},
- {S3XAmzCopySource,
- NewValueSet(
- NewStringValue("mybucket/*"),
- NewStringValue("yourbucket/myobject*"),
- ), case2Function, false},
-
- {S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES*")), case3Function, false},
- {S3XAmzServerSideEncryption,
- NewValueSet(
- NewStringValue("AES*"),
- ), case4Function, false},
-
- {S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPL*")), case5Function, false},
- {S3XAmzMetadataDirective,
- NewValueSet(
- NewStringValue("REPL*"),
- NewStringValue("COPY*"),
- ), case6Function, false},
-
- {S3LocationConstraint, NewValueSet(NewStringValue("eu-west-*")), case7Function, false},
- {S3LocationConstraint,
- NewValueSet(
- NewStringValue("eu-west-*"),
- NewStringValue("us-west-*"),
- ), case8Function, false},
-
- // Unsupported value error.
- {S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject"), NewIntValue(7)), nil, true},
- {S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256"), NewIntValue(7)), nil, true},
- {S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE"), NewIntValue(7)), nil, true},
- {S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1"), NewIntValue(7)), nil, true},
-
- // Invalid value error.
- {S3XAmzCopySource, NewValueSet(NewStringValue("mybucket")), nil, true},
- }
-
- for i, testCase := range testCases {
- result, err := newStringNotLikeFunc(testCase.key, testCase.values)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
diff --git a/pkg/bucket/policy/condition/value.go b/pkg/bucket/policy/condition/value.go
deleted file mode 100644
index 80b4922d4..000000000
--- a/pkg/bucket/policy/condition/value.go
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "encoding/json"
- "fmt"
- "reflect"
- "strconv"
- "strings"
-)
-
-// Splits an incoming path into bucket and object components.
-func path2BucketAndObject(path string) (bucket, object string) {
- // Skip the first element if it is '/', split the rest.
- path = strings.TrimPrefix(path, "/")
- pathComponents := strings.SplitN(path, "/", 2)
-
- // Save the bucket and object extracted from path.
- switch len(pathComponents) {
- case 1:
- bucket = pathComponents[0]
- case 2:
- bucket = pathComponents[0]
- object = pathComponents[1]
- }
- return bucket, object
-}
-
-// Value - is enum type of string, int or bool.
-type Value struct {
- t reflect.Kind
- s string
- i int
- b bool
-}
-
-// GetBool - gets stored bool value.
-func (v Value) GetBool() (bool, error) {
- var err error
-
- if v.t != reflect.Bool {
- err = fmt.Errorf("not a bool Value")
- }
-
- return v.b, err
-}
-
-// GetInt - gets stored int value.
-func (v Value) GetInt() (int, error) {
- var err error
-
- if v.t != reflect.Int {
- err = fmt.Errorf("not a int Value")
- }
-
- return v.i, err
-}
-
-// GetString - gets stored string value.
-func (v Value) GetString() (string, error) {
- var err error
-
- if v.t != reflect.String {
- err = fmt.Errorf("not a string Value")
- }
-
- return v.s, err
-}
-
-// GetType - gets enum type.
-func (v Value) GetType() reflect.Kind {
- return v.t
-}
-
-// MarshalJSON - encodes Value to JSON data.
-func (v Value) MarshalJSON() ([]byte, error) {
- switch v.t {
- case reflect.String:
- return json.Marshal(v.s)
- case reflect.Int:
- return json.Marshal(v.i)
- case reflect.Bool:
- return json.Marshal(v.b)
- }
-
- return nil, fmt.Errorf("unknown value kind %v", v.t)
-}
-
-// StoreBool - stores bool value.
-func (v *Value) StoreBool(b bool) {
- *v = Value{t: reflect.Bool, b: b}
-}
-
-// StoreInt - stores int value.
-func (v *Value) StoreInt(i int) {
- *v = Value{t: reflect.Int, i: i}
-}
-
-// StoreString - stores string value.
-func (v *Value) StoreString(s string) {
- *v = Value{t: reflect.String, s: s}
-}
-
-// String - returns string representation of value.
-func (v Value) String() string {
- switch v.t {
- case reflect.String:
- return v.s
- case reflect.Int:
- return strconv.Itoa(v.i)
- case reflect.Bool:
- return strconv.FormatBool(v.b)
- }
-
- return ""
-}
-
-// UnmarshalJSON - decodes JSON data.
-func (v *Value) UnmarshalJSON(data []byte) error {
- var b bool
- if err := json.Unmarshal(data, &b); err == nil {
- v.StoreBool(b)
- return nil
- }
-
- var i int
- if err := json.Unmarshal(data, &i); err == nil {
- v.StoreInt(i)
- return nil
- }
-
- var s string
- if err := json.Unmarshal(data, &s); err == nil {
- v.StoreString(s)
- return nil
- }
-
- return fmt.Errorf("unknown json data '%v'", data)
-}
-
-// NewBoolValue - returns new bool value.
-func NewBoolValue(b bool) Value {
- value := &Value{}
- value.StoreBool(b)
- return *value
-}
-
-// NewIntValue - returns new int value.
-func NewIntValue(i int) Value {
- value := &Value{}
- value.StoreInt(i)
- return *value
-}
-
-// NewStringValue - returns new string value.
-func NewStringValue(s string) Value {
- value := &Value{}
- value.StoreString(s)
- return *value
-}
diff --git a/pkg/bucket/policy/condition/value_test.go b/pkg/bucket/policy/condition/value_test.go
deleted file mode 100644
index eac97321a..000000000
--- a/pkg/bucket/policy/condition/value_test.go
+++ /dev/null
@@ -1,261 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "encoding/json"
- "reflect"
- "testing"
-)
-
-func TestValueGetBool(t *testing.T) {
- testCases := []struct {
- value Value
- expectedResult bool
- expectErr bool
- }{
- {NewBoolValue(true), true, false},
- {NewIntValue(7), false, true},
- {Value{}, false, true},
- }
-
- for i, testCase := range testCases {
- result, err := testCase.value.GetBool()
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if result != testCase.expectedResult {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
-
-func TestValueGetInt(t *testing.T) {
- testCases := []struct {
- value Value
- expectedResult int
- expectErr bool
- }{
- {NewIntValue(7), 7, false},
- {NewBoolValue(true), 0, true},
- {Value{}, 0, true},
- }
-
- for i, testCase := range testCases {
- result, err := testCase.value.GetInt()
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if result != testCase.expectedResult {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
-
-func TestValueGetString(t *testing.T) {
- testCases := []struct {
- value Value
- expectedResult string
- expectErr bool
- }{
- {NewStringValue("foo"), "foo", false},
- {NewBoolValue(true), "", true},
- {Value{}, "", true},
- }
-
- for i, testCase := range testCases {
- result, err := testCase.value.GetString()
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if result != testCase.expectedResult {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
-
-func TestValueGetType(t *testing.T) {
- testCases := []struct {
- value Value
- expectedResult reflect.Kind
- }{
- {NewBoolValue(true), reflect.Bool},
- {NewIntValue(7), reflect.Int},
- {NewStringValue("foo"), reflect.String},
- {Value{}, reflect.Invalid},
- }
-
- for i, testCase := range testCases {
- result := testCase.value.GetType()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestValueMarshalJSON(t *testing.T) {
- testCases := []struct {
- value Value
- expectedResult []byte
- expectErr bool
- }{
- {NewBoolValue(true), []byte("true"), false},
- {NewIntValue(7), []byte("7"), false},
- {NewStringValue("foo"), []byte(`"foo"`), false},
- {Value{}, nil, true},
- }
-
- for i, testCase := range testCases {
- result, err := json.Marshal(testCase.value)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
-
-func TestValueStoreBool(t *testing.T) {
- testCases := []struct {
- value bool
- expectedResult Value
- }{
- {false, NewBoolValue(false)},
- {true, NewBoolValue(true)},
- }
-
- for i, testCase := range testCases {
- var result Value
- result.StoreBool(testCase.value)
-
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestValueStoreInt(t *testing.T) {
- testCases := []struct {
- value int
- expectedResult Value
- }{
- {0, NewIntValue(0)},
- {7, NewIntValue(7)},
- }
-
- for i, testCase := range testCases {
- var result Value
- result.StoreInt(testCase.value)
-
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestValueStoreString(t *testing.T) {
- testCases := []struct {
- value string
- expectedResult Value
- }{
- {"", NewStringValue("")},
- {"foo", NewStringValue("foo")},
- }
-
- for i, testCase := range testCases {
- var result Value
- result.StoreString(testCase.value)
-
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestValueString(t *testing.T) {
- testCases := []struct {
- value Value
- expectedResult string
- }{
- {NewBoolValue(true), "true"},
- {NewIntValue(7), "7"},
- {NewStringValue("foo"), "foo"},
- {Value{}, ""},
- }
-
- for i, testCase := range testCases {
- result := testCase.value.String()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestValueUnmarshalJSON(t *testing.T) {
- testCases := []struct {
- data []byte
- expectedResult Value
- expectErr bool
- }{
- {[]byte("true"), NewBoolValue(true), false},
- {[]byte("7"), NewIntValue(7), false},
- {[]byte(`"foo"`), NewStringValue("foo"), false},
- {[]byte("True"), Value{}, true},
- {[]byte("7.1"), Value{}, true},
- {[]byte(`["foo"]`), Value{}, true},
- }
-
- for i, testCase := range testCases {
- var result Value
- err := json.Unmarshal(testCase.data, &result)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
diff --git a/pkg/bucket/policy/condition/valueset.go b/pkg/bucket/policy/condition/valueset.go
deleted file mode 100644
index f97bdd68a..000000000
--- a/pkg/bucket/policy/condition/valueset.go
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "encoding/json"
- "fmt"
-)
-
-// ValueSet - unique list of values.
-type ValueSet map[Value]struct{}
-
-// Add - adds given value to value set.
-func (set ValueSet) Add(value Value) {
- set[value] = struct{}{}
-}
-
-// ToSlice converts ValueSet to a slice of Value
-func (set ValueSet) ToSlice() []Value {
- var values []Value
- for k := range set {
- values = append(values, k)
- }
- return values
-}
-
-// MarshalJSON - encodes ValueSet to JSON data.
-func (set ValueSet) MarshalJSON() ([]byte, error) {
- var values []Value
- for k := range set {
- values = append(values, k)
- }
-
- if len(values) == 0 {
- return nil, fmt.Errorf("invalid value set %v", set)
- }
-
- return json.Marshal(values)
-}
-
-// UnmarshalJSON - decodes JSON data.
-func (set *ValueSet) UnmarshalJSON(data []byte) error {
- var v Value
- if err := json.Unmarshal(data, &v); err == nil {
- *set = make(ValueSet)
- set.Add(v)
- return nil
- }
-
- var values []Value
- if err := json.Unmarshal(data, &values); err != nil {
- return err
- }
-
- if len(values) < 1 {
- return fmt.Errorf("invalid value")
- }
-
- *set = make(ValueSet)
- for _, v = range values {
- if _, found := (*set)[v]; found {
- return fmt.Errorf("duplicate value found '%v'", v)
- }
-
- set.Add(v)
- }
-
- return nil
-}
-
-// Clone clones ValueSet structure
-func (set ValueSet) Clone() ValueSet {
- return NewValueSet(set.ToSlice()...)
-}
-
-// NewValueSet - returns new value set containing given values.
-func NewValueSet(values ...Value) ValueSet {
- set := make(ValueSet)
-
- for _, value := range values {
- set.Add(value)
- }
-
- return set
-}
diff --git a/pkg/bucket/policy/condition/valueset_test.go b/pkg/bucket/policy/condition/valueset_test.go
deleted file mode 100644
index f727edd3c..000000000
--- a/pkg/bucket/policy/condition/valueset_test.go
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package condition
-
-import (
- "encoding/json"
- "reflect"
- "testing"
-)
-
-func TestValueSetAdd(t *testing.T) {
- testCases := []struct {
- value Value
- expectedResult ValueSet
- }{
- {NewBoolValue(true), NewValueSet(NewBoolValue(true))},
- {NewIntValue(7), NewValueSet(NewIntValue(7))},
- {NewStringValue("foo"), NewValueSet(NewStringValue("foo"))},
- }
-
- for i, testCase := range testCases {
- result := NewValueSet()
- result.Add(testCase.value)
-
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestValueSetMarshalJSON(t *testing.T) {
- testCases := []struct {
- set ValueSet
- expectedResult string
- expectErr bool
- }{
- {NewValueSet(NewBoolValue(true)), `[true]`, false},
- {NewValueSet(NewIntValue(7)), `[7]`, false},
- {NewValueSet(NewStringValue("foo")), `["foo"]`, false},
- {NewValueSet(NewBoolValue(true)), `[true]`, false},
- {NewValueSet(NewStringValue("7")), `["7"]`, false},
- {NewValueSet(NewStringValue("foo")), `["foo"]`, false},
- {make(ValueSet), "", true},
- }
-
- for i, testCase := range testCases {
- result, err := json.Marshal(testCase.set)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if string(result) != testCase.expectedResult {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, string(result))
- }
- }
- }
-}
-
-func TestValueSetUnmarshalJSON(t *testing.T) {
- set1 := NewValueSet(
- NewBoolValue(true),
- NewStringValue("false"),
- NewIntValue(7),
- NewStringValue("7"),
- NewStringValue("foo"),
- NewStringValue("192.168.1.100/24"),
- )
-
- testCases := []struct {
- data []byte
- expectedResult ValueSet
- expectErr bool
- }{
- {[]byte(`true`), NewValueSet(NewBoolValue(true)), false},
- {[]byte(`7`), NewValueSet(NewIntValue(7)), false},
- {[]byte(`"foo"`), NewValueSet(NewStringValue("foo")), false},
- {[]byte(`[true]`), NewValueSet(NewBoolValue(true)), false},
- {[]byte(`[7]`), NewValueSet(NewIntValue(7)), false},
- {[]byte(`["foo"]`), NewValueSet(NewStringValue("foo")), false},
- {[]byte(`[true, "false", 7, "7", "foo", "192.168.1.100/24"]`), set1, false},
- {[]byte(`{}`), nil, true}, // Unsupported data.
- {[]byte(`[]`), nil, true}, // Empty array.
- {[]byte(`[7, 7, true]`), nil, true}, // Duplicate value.
- }
-
- for i, testCase := range testCases {
- result := make(ValueSet)
- err := json.Unmarshal(testCase.data, &result)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
diff --git a/pkg/bucket/policy/effect.go b/pkg/bucket/policy/effect.go
deleted file mode 100644
index e6f6c3ad6..000000000
--- a/pkg/bucket/policy/effect.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package policy
-
-// Effect - policy statement effect Allow or Deny.
-type Effect string
-
-const (
- // Allow - allow effect.
- Allow Effect = "Allow"
-
- // Deny - deny effect.
- Deny = "Deny"
-)
-
-// IsAllowed - returns if given check is allowed or not.
-func (effect Effect) IsAllowed(b bool) bool {
- if effect == Allow {
- return b
- }
-
- return !b
-}
-
-// IsValid - checks if Effect is valid or not
-func (effect Effect) IsValid() bool {
- switch effect {
- case Allow, Deny:
- return true
- }
-
- return false
-}
diff --git a/pkg/bucket/policy/effect_test.go b/pkg/bucket/policy/effect_test.go
deleted file mode 100644
index 86eb7c20d..000000000
--- a/pkg/bucket/policy/effect_test.go
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package policy
-
-import (
- "testing"
-)
-
-func TestEffectIsAllowed(t *testing.T) {
- testCases := []struct {
- effect Effect
- check bool
- expectedResult bool
- }{
- {Allow, false, false},
- {Allow, true, true},
- {Deny, false, true},
- {Deny, true, false},
- }
-
- for i, testCase := range testCases {
- result := testCase.effect.IsAllowed(testCase.check)
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-
-}
-
-func TestEffectIsValid(t *testing.T) {
- testCases := []struct {
- effect Effect
- expectedResult bool
- }{
- {Allow, true},
- {Deny, true},
- {Effect(""), false},
- {Effect("foo"), false},
- }
-
- for i, testCase := range testCases {
- result := testCase.effect.IsValid()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
diff --git a/pkg/bucket/policy/error.go b/pkg/bucket/policy/error.go
deleted file mode 100644
index e0b8c6d01..000000000
--- a/pkg/bucket/policy/error.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package policy
-
-import (
- "fmt"
-)
-
-// Error is the generic type for any error happening during policy
-// parsing.
-type Error struct {
- err error
-}
-
-// Errorf - formats according to a format specifier and returns
-// the string as a value that satisfies error of type policy.Error
-func Errorf(format string, a ...interface{}) error {
- return Error{err: fmt.Errorf(format, a...)}
-}
-
-// Unwrap the internal error.
-func (e Error) Unwrap() error { return e.err }
-
-// Error 'error' compatible method.
-func (e Error) Error() string {
- if e.err == nil {
- return "policy: cause "
- }
- return e.err.Error()
-}
diff --git a/pkg/bucket/policy/id.go b/pkg/bucket/policy/id.go
deleted file mode 100644
index ad7f966c9..000000000
--- a/pkg/bucket/policy/id.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package policy
-
-import (
- "unicode/utf8"
-)
-
-// ID - policy ID.
-type ID string
-
-// IsValid - checks if ID is valid or not.
-func (id ID) IsValid() bool {
- return utf8.ValidString(string(id))
-}
diff --git a/pkg/bucket/policy/id_test.go b/pkg/bucket/policy/id_test.go
deleted file mode 100644
index 42f969306..000000000
--- a/pkg/bucket/policy/id_test.go
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package policy
-
-import (
- "testing"
-)
-
-func TestIDIsValid(t *testing.T) {
- testCases := []struct {
- id ID
- expectedResult bool
- }{
- {ID("DenyEncryptionSt1"), true},
- {ID(""), true},
- {ID("aa\xe2"), false},
- }
-
- for i, testCase := range testCases {
- result := testCase.id.IsValid()
-
- if result != testCase.expectedResult {
- t.Errorf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
diff --git a/pkg/bucket/policy/policy.go b/pkg/bucket/policy/policy.go
deleted file mode 100644
index 25c578aa0..000000000
--- a/pkg/bucket/policy/policy.go
+++ /dev/null
@@ -1,185 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package policy
-
-import (
- "encoding/json"
- "io"
-)
-
-// DefaultVersion - default policy version as per AWS S3 specification.
-const DefaultVersion = "2012-10-17"
-
-// Args - arguments to policy to check whether it is allowed
-type Args struct {
- AccountName string `json:"account"`
- Groups []string `json:"groups"`
- Action Action `json:"action"`
- BucketName string `json:"bucket"`
- ConditionValues map[string][]string `json:"conditions"`
- IsOwner bool `json:"owner"`
- ObjectName string `json:"object"`
-}
-
-// Policy - bucket policy.
-type Policy struct {
- ID ID `json:"ID,omitempty"`
- Version string
- Statements []Statement `json:"Statement"`
-}
-
-// IsAllowed - checks given policy args is allowed to continue the Rest API.
-func (policy Policy) IsAllowed(args Args) bool {
- // Check all deny statements. If any one statement denies, return false.
- for _, statement := range policy.Statements {
- if statement.Effect == Deny {
- if !statement.IsAllowed(args) {
- return false
- }
- }
- }
-
- // For owner, its allowed by default.
- if args.IsOwner {
- return true
- }
-
- // Check all allow statements. If any one statement allows, return true.
- for _, statement := range policy.Statements {
- if statement.Effect == Allow {
- if statement.IsAllowed(args) {
- return true
- }
- }
- }
-
- return false
-}
-
-// IsEmpty - returns whether policy is empty or not.
-func (policy Policy) IsEmpty() bool {
- return len(policy.Statements) == 0
-}
-
-// isValid - checks if Policy is valid or not.
-func (policy Policy) isValid() error {
- if policy.Version != DefaultVersion && policy.Version != "" {
- return Errorf("invalid version '%v'", policy.Version)
- }
-
- for _, statement := range policy.Statements {
- if err := statement.isValid(); err != nil {
- return err
- }
- }
-
- return nil
-}
-
-// MarshalJSON - encodes Policy to JSON data.
-func (policy Policy) MarshalJSON() ([]byte, error) {
- if err := policy.isValid(); err != nil {
- return nil, err
- }
-
- // subtype to avoid recursive call to MarshalJSON()
- type subPolicy Policy
- return json.Marshal(subPolicy(policy))
-}
-
-// Merge merges two policies documents and drop
-// duplicate statements if any.
-func (policy Policy) Merge(input Policy) Policy {
- var mergedPolicy Policy
- if policy.Version != "" {
- mergedPolicy.Version = policy.Version
- } else {
- mergedPolicy.Version = input.Version
- }
- for _, st := range policy.Statements {
- mergedPolicy.Statements = append(mergedPolicy.Statements, st.Clone())
- }
- for _, st := range input.Statements {
- mergedPolicy.Statements = append(mergedPolicy.Statements, st.Clone())
- }
- mergedPolicy.dropDuplicateStatements()
- return mergedPolicy
-}
-
-func (policy *Policy) dropDuplicateStatements() {
-redo:
- for i := range policy.Statements {
- for j, statement := range policy.Statements[i+1:] {
- if !policy.Statements[i].Equals(statement) {
- continue
- }
- policy.Statements = append(policy.Statements[:j], policy.Statements[j+1:]...)
- goto redo
- }
- }
-}
-
-// UnmarshalJSON - decodes JSON data to Policy.
-func (policy *Policy) UnmarshalJSON(data []byte) error {
- // subtype to avoid recursive call to UnmarshalJSON()
- type subPolicy Policy
- var sp subPolicy
- if err := json.Unmarshal(data, &sp); err != nil {
- return err
- }
-
- p := Policy(sp)
- if err := p.isValid(); err != nil {
- return err
- }
-
- p.dropDuplicateStatements()
-
- *policy = p
-
- return nil
-}
-
-// Validate - validates all statements are for given bucket or not.
-func (policy Policy) Validate(bucketName string) error {
- if err := policy.isValid(); err != nil {
- return err
- }
-
- for _, statement := range policy.Statements {
- if err := statement.Validate(bucketName); err != nil {
- return err
- }
- }
-
- return nil
-}
-
-// ParseConfig - parses data in given reader to Policy.
-func ParseConfig(reader io.Reader, bucketName string) (*Policy, error) {
- var policy Policy
-
- decoder := json.NewDecoder(reader)
- decoder.DisallowUnknownFields()
- if err := decoder.Decode(&policy); err != nil {
- return nil, Errorf("%w", err)
- }
-
- err := policy.Validate(bucketName)
- return &policy, err
-}
diff --git a/pkg/bucket/policy/policy_test.go b/pkg/bucket/policy/policy_test.go
deleted file mode 100644
index 257675425..000000000
--- a/pkg/bucket/policy/policy_test.go
+++ /dev/null
@@ -1,1241 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package policy
-
-import (
- "encoding/json"
- "net"
- "reflect"
- "testing"
-
- "github.com/minio/minio/pkg/bucket/policy/condition"
-)
-
-func TestPolicyIsAllowed(t *testing.T) {
- case1Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(GetBucketLocationAction, PutObjectAction),
- NewResourceSet(NewResource("*", "")),
- condition.NewFunctions(),
- )},
- }
-
- case2Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(GetObjectAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- )},
- }
-
- _, IPNet, err := net.ParseCIDR("192.168.1.0/24")
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- func1, err := condition.NewIPAddressFunc(
- condition.AWSSourceIP,
- IPNet,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(GetObjectAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(func1),
- )},
- }
-
- case4Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Deny,
- NewPrincipal("*"),
- NewActionSet(GetObjectAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(func1),
- )},
- }
-
- anonGetBucketLocationArgs := Args{
- AccountName: "Q3AM3UQ867SPQQA43P2F",
- Action: GetBucketLocationAction,
- BucketName: "mybucket",
- ConditionValues: map[string][]string{},
- }
-
- anonPutObjectActionArgs := Args{
- AccountName: "Q3AM3UQ867SPQQA43P2F",
- Action: PutObjectAction,
- BucketName: "mybucket",
- ConditionValues: map[string][]string{
- "x-amz-copy-source": {"mybucket/myobject"},
- "SourceIp": {"192.168.1.10"},
- },
- ObjectName: "myobject",
- }
-
- anonGetObjectActionArgs := Args{
- AccountName: "Q3AM3UQ867SPQQA43P2F",
- Action: GetObjectAction,
- BucketName: "mybucket",
- ConditionValues: map[string][]string{},
- ObjectName: "myobject",
- }
-
- getBucketLocationArgs := Args{
- AccountName: "Q3AM3UQ867SPQQA43P2F",
- Action: GetBucketLocationAction,
- BucketName: "mybucket",
- ConditionValues: map[string][]string{},
- IsOwner: true,
- }
-
- putObjectActionArgs := Args{
- AccountName: "Q3AM3UQ867SPQQA43P2F",
- Action: PutObjectAction,
- BucketName: "mybucket",
- ConditionValues: map[string][]string{
- "x-amz-copy-source": {"mybucket/myobject"},
- "SourceIp": {"192.168.1.10"},
- },
- IsOwner: true,
- ObjectName: "myobject",
- }
-
- getObjectActionArgs := Args{
- AccountName: "Q3AM3UQ867SPQQA43P2F",
- Action: GetObjectAction,
- BucketName: "mybucket",
- ConditionValues: map[string][]string{},
- IsOwner: true,
- ObjectName: "myobject",
- }
-
- testCases := []struct {
- policy Policy
- args Args
- expectedResult bool
- }{
- {case1Policy, anonGetBucketLocationArgs, true},
- {case1Policy, anonPutObjectActionArgs, true},
- {case1Policy, anonGetObjectActionArgs, false},
- {case1Policy, getBucketLocationArgs, true},
- {case1Policy, putObjectActionArgs, true},
- {case1Policy, getObjectActionArgs, true},
-
- {case2Policy, anonGetBucketLocationArgs, false},
- {case2Policy, anonPutObjectActionArgs, true},
- {case2Policy, anonGetObjectActionArgs, true},
- {case2Policy, getBucketLocationArgs, true},
- {case2Policy, putObjectActionArgs, true},
- {case2Policy, getObjectActionArgs, true},
-
- {case3Policy, anonGetBucketLocationArgs, false},
- {case3Policy, anonPutObjectActionArgs, true},
- {case3Policy, anonGetObjectActionArgs, false},
- {case3Policy, getBucketLocationArgs, true},
- {case3Policy, putObjectActionArgs, true},
- {case3Policy, getObjectActionArgs, true},
-
- {case4Policy, anonGetBucketLocationArgs, false},
- {case4Policy, anonPutObjectActionArgs, false},
- {case4Policy, anonGetObjectActionArgs, false},
- {case4Policy, getBucketLocationArgs, true},
- {case4Policy, putObjectActionArgs, false},
- {case4Policy, getObjectActionArgs, true},
- }
-
- for i, testCase := range testCases {
- result := testCase.policy.IsAllowed(testCase.args)
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestPolicyIsEmpty(t *testing.T) {
- case1Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- case2Policy := Policy{
- ID: "MyPolicyForMyBucket",
- Version: DefaultVersion,
- }
-
- testCases := []struct {
- policy Policy
- expectedResult bool
- }{
- {case1Policy, false},
- {case2Policy, true},
- }
-
- for i, testCase := range testCases {
- result := testCase.policy.IsEmpty()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestPolicyIsValid(t *testing.T) {
- case1Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- case2Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- NewStatement(
- Deny,
- NewPrincipal("*"),
- NewActionSet(GetObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- case3Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- NewStatement(
- Deny,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/yourobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- func1, err := condition.NewNullFunc(
- condition.S3XAmzCopySource,
- true,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- func2, err := condition.NewNullFunc(
- condition.S3XAmzServerSideEncryption,
- false,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(func1),
- ),
- NewStatement(
- Deny,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(func2),
- ),
- },
- }
-
- case5Policy := Policy{
- Version: "17-10-2012",
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- case6Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(GetObjectAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "myobject*")),
- condition.NewFunctions(func1, func2),
- ),
- },
- }
-
- case7Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- NewStatement(
- Deny,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- case8Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- testCases := []struct {
- policy Policy
- expectErr bool
- }{
- {case1Policy, false},
- // allowed duplicate principal.
- {case2Policy, false},
- // allowed duplicate principal and action.
- {case3Policy, false},
- // allowed duplicate principal, action and resource.
- {case4Policy, false},
- // Invalid version error.
- {case5Policy, true},
- // Invalid statement error.
- {case6Policy, true},
- // Duplicate statement success different effects.
- {case7Policy, false},
- // Duplicate statement success, duplicate statement dropped.
- {case8Policy, false},
- }
-
- for i, testCase := range testCases {
- err := testCase.policy.isValid()
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
- }
-}
-
-func TestPolicyMarshalJSON(t *testing.T) {
- case1Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
- case1Policy.Statements[0].SID = "SomeId1"
- case1Data := []byte(`{"ID":"MyPolicyForMyBucket1","Version":"2012-10-17","Statement":[{"Sid":"SomeId1","Effect":"Allow","Principal":{"AWS":["*"]},"Action":["s3:PutObject"],"Resource":["arn:aws:s3:::mybucket/myobject*"]}]}`)
-
- _, IPNet1, err := net.ParseCIDR("192.168.1.0/24")
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- func1, err := condition.NewIPAddressFunc(
- condition.AWSSourceIP,
- IPNet1,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- NewStatement(
- Deny,
- NewPrincipal("*"),
- NewActionSet(GetObjectAction),
- NewResourceSet(NewResource("mybucket", "/yourobject*")),
- condition.NewFunctions(func1),
- ),
- },
- }
- case2Data := []byte(`{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":["*"]},"Action":["s3:PutObject"],"Resource":["arn:aws:s3:::mybucket/myobject*"]},{"Effect":"Deny","Principal":{"AWS":["*"]},"Action":["s3:GetObject"],"Resource":["arn:aws:s3:::mybucket/yourobject*"],"Condition":{"IpAddress":{"aws:SourceIp":["192.168.1.0/24"]}}}]}`)
-
- case3Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("Q3AM3UQ867SPQQA43P2F"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
- case3Data := []byte(`{"ID":"MyPolicyForMyBucket1","Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":["Q3AM3UQ867SPQQA43P2F"]},"Action":["s3:PutObject"],"Resource":["arn:aws:s3:::mybucket/myobject*"]},{"Effect":"Allow","Principal":{"AWS":["*"]},"Action":["s3:PutObject"],"Resource":["arn:aws:s3:::mybucket/myobject*"]}]}`)
-
- case4Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(GetObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
- case4Data := []byte(`{"ID":"MyPolicyForMyBucket1","Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":["*"]},"Action":["s3:PutObject"],"Resource":["arn:aws:s3:::mybucket/myobject*"]},{"Effect":"Allow","Principal":{"AWS":["*"]},"Action":["s3:GetObject"],"Resource":["arn:aws:s3:::mybucket/myobject*"]}]}`)
-
- case5Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/yourobject*")),
- condition.NewFunctions(),
- ),
- },
- }
- case5Data := []byte(`{"ID":"MyPolicyForMyBucket1","Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":["*"]},"Action":["s3:PutObject"],"Resource":["arn:aws:s3:::mybucket/myobject*"]},{"Effect":"Allow","Principal":{"AWS":["*"]},"Action":["s3:PutObject"],"Resource":["arn:aws:s3:::mybucket/yourobject*"]}]}`)
-
- _, IPNet2, err := net.ParseCIDR("192.168.2.0/24")
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- func2, err := condition.NewIPAddressFunc(
- condition.AWSSourceIP,
- IPNet2,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case6Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(func1),
- ),
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(func2),
- ),
- },
- }
- case6Data := []byte(`{"ID":"MyPolicyForMyBucket1","Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":["*"]},"Action":["s3:PutObject"],"Resource":["arn:aws:s3:::mybucket/myobject*"],"Condition":{"IpAddress":{"aws:SourceIp":["192.168.1.0/24"]}}},{"Effect":"Allow","Principal":{"AWS":["*"]},"Action":["s3:PutObject"],"Resource":["arn:aws:s3:::mybucket/myobject*"],"Condition":{"IpAddress":{"aws:SourceIp":["192.168.2.0/24"]}}}]}`)
-
- case7Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(GetBucketLocationAction),
- NewResourceSet(NewResource("mybucket", "")),
- condition.NewFunctions(),
- ),
- },
- }
- case7Data := []byte(`{"ID":"MyPolicyForMyBucket1","Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":["*"]},"Action":["s3:GetBucketLocation"],"Resource":["arn:aws:s3:::mybucket"]}]}`)
-
- case8Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(GetBucketLocationAction),
- NewResourceSet(NewResource("*", "")),
- condition.NewFunctions(),
- ),
- },
- }
- case8Data := []byte(`{"ID":"MyPolicyForMyBucket1","Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":["*"]},"Action":["s3:GetBucketLocation"],"Resource":["arn:aws:s3:::*"]}]}`)
-
- func3, err := condition.NewNullFunc(
- condition.S3XAmzCopySource,
- true,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- case9Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(GetObjectAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "myobject*")),
- condition.NewFunctions(func1, func2, func3),
- ),
- },
- }
-
- testCases := []struct {
- policy Policy
- expectedResult []byte
- expectErr bool
- }{
- {case1Policy, case1Data, false},
- {case2Policy, case2Data, false},
- {case3Policy, case3Data, false},
- {case4Policy, case4Data, false},
- {case5Policy, case5Data, false},
- {case6Policy, case6Data, false},
- {case7Policy, case7Data, false},
- {case8Policy, case8Data, false},
- {case9Policy, nil, true},
- }
-
- for i, testCase := range testCases {
- result, err := json.Marshal(testCase.policy)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v", i+1, string(testCase.expectedResult), string(result))
- }
- }
- }
-}
-
-func TestPolicyUnmarshalJSON(t *testing.T) {
- case1Data := []byte(`{
- "ID": "MyPolicyForMyBucket1",
- "Version": "2012-10-17",
- "Statement": [
- {
- "Sid": "SomeId1",
- "Effect": "Allow",
- "Principal": "*",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
- }
- ]
-}`)
- case1Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
- case1Policy.Statements[0].SID = "SomeId1"
-
- case2Data := []byte(`{
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Principal": "*",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
- },
- {
- "Effect": "Deny",
- "Principal": "*",
- "Action": "s3:GetObject",
- "Resource": "arn:aws:s3:::mybucket/yourobject*",
- "Condition": {
- "IpAddress": {
- "aws:SourceIp": "192.168.1.0/24"
- }
- }
- }
- ]
-}`)
- _, IPNet1, err := net.ParseCIDR("192.168.1.0/24")
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- func1, err := condition.NewIPAddressFunc(
- condition.AWSSourceIP,
- IPNet1,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- NewStatement(
- Deny,
- NewPrincipal("*"),
- NewActionSet(GetObjectAction),
- NewResourceSet(NewResource("mybucket", "/yourobject*")),
- condition.NewFunctions(func1),
- ),
- },
- }
-
- case3Data := []byte(`{
- "ID": "MyPolicyForMyBucket1",
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Principal": {
- "AWS": [
- "Q3AM3UQ867SPQQA43P2F"
- ]
- },
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
- },
- {
- "Effect": "Allow",
- "Principal": "*",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
- }
- ]
-}`)
- case3Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("Q3AM3UQ867SPQQA43P2F"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- case4Data := []byte(`{
- "ID": "MyPolicyForMyBucket1",
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Principal": "*",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
- },
- {
- "Effect": "Allow",
- "Principal": "*",
- "Action": "s3:GetObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
- }
- ]
-}`)
- case4Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(GetObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- case5Data := []byte(`{
- "ID": "MyPolicyForMyBucket1",
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Principal": "*",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
- },
- {
- "Effect": "Allow",
- "Principal": "*",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/yourobject*"
- }
- ]
-}`)
- case5Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/yourobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- case6Data := []byte(`{
- "ID": "MyPolicyForMyBucket1",
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Principal": "*",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*",
- "Condition": {
- "IpAddress": {
- "aws:SourceIp": "192.168.1.0/24"
- }
- }
- },
- {
- "Effect": "Allow",
- "Principal": "*",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*",
- "Condition": {
- "IpAddress": {
- "aws:SourceIp": "192.168.2.0/24"
- }
- }
- }
- ]
-}`)
- _, IPNet2, err := net.ParseCIDR("192.168.2.0/24")
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- func2, err := condition.NewIPAddressFunc(
- condition.AWSSourceIP,
- IPNet2,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case6Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(func1),
- ),
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(func2),
- ),
- },
- }
-
- case7Data := []byte(`{
- "ID": "MyPolicyForMyBucket1",
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Principal": "*",
- "Action": "s3:GetBucketLocation",
- "Resource": "arn:aws:s3:::mybucket"
- }
- ]
-}`)
-
- case7Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(GetBucketLocationAction),
- NewResourceSet(NewResource("mybucket", "")),
- condition.NewFunctions(),
- ),
- },
- }
-
- case8Data := []byte(`{
- "ID": "MyPolicyForMyBucket1",
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Principal": "*",
- "Action": "s3:GetBucketLocation",
- "Resource": "arn:aws:s3:::*"
- }
- ]
-}`)
-
- case8Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(GetBucketLocationAction),
- NewResourceSet(NewResource("*", "")),
- condition.NewFunctions(),
- ),
- },
- }
-
- case9Data := []byte(`{
- "ID": "MyPolicyForMyBucket1",
- "Version": "17-10-2012",
- "Statement": [
- {
- "Effect": "Allow",
- "Principal": "*",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
- }
- ]
-}`)
-
- case10Data := []byte(`{
- "ID": "MyPolicyForMyBucket1",
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Principal": "*",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
- },
- {
- "Effect": "Allow",
- "Principal": "*",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
- }
- ]
-}`)
-
- case10Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- case11Data := []byte(`{
- "ID": "MyPolicyForMyBucket1",
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Principal": "*",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
- },
- {
- "Effect": "Deny",
- "Principal": "*",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
- }
- ]
-}`)
-
- case11Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "myobject*")),
- condition.NewFunctions(),
- ),
- NewStatement(
- Deny,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- testCases := []struct {
- data []byte
- expectedResult Policy
- expectErr bool
- }{
- {case1Data, case1Policy, false},
- {case2Data, case2Policy, false},
- {case3Data, case3Policy, false},
- {case4Data, case4Policy, false},
- {case5Data, case5Policy, false},
- {case6Data, case6Policy, false},
- {case7Data, case7Policy, false},
- {case8Data, case8Policy, false},
- // Invalid version error.
- {case9Data, Policy{}, true},
- // Duplicate statement success, duplicate statement removed.
- {case10Data, case10Policy, false},
- // Duplicate statement success (Effect differs).
- {case11Data, case11Policy, false},
- }
-
- for i, testCase := range testCases {
- var result Policy
- err := json.Unmarshal(testCase.data, &result)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Errorf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Errorf("case %v: result: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
-
-func TestPolicyValidate(t *testing.T) {
- case1Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- func1, err := condition.NewNullFunc(
- condition.S3XAmzCopySource,
- true,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- func2, err := condition.NewNullFunc(
- condition.S3XAmzServerSideEncryption,
- false,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- case2Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(GetObjectAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "myobject*")),
- condition.NewFunctions(func1, func2),
- ),
- },
- }
-
- testCases := []struct {
- policy Policy
- bucketName string
- expectErr bool
- }{
- {case1Policy, "mybucket", false},
- {case2Policy, "yourbucket", true},
- {case1Policy, "yourbucket", true},
- }
-
- for i, testCase := range testCases {
- err := testCase.policy.Validate(testCase.bucketName)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
- }
-}
-
-func TestPolicyMerge(t *testing.T) {
- testCases := []struct {
- policy string
- }{
- {`{
- "Version": "2012-10-17",
- "Id": "S3PolicyId1",
- "Statement": [
- {
- "Sid": "statement1",
- "Effect": "Deny",
- "Principal": "*",
- "Action":["s3:GetObject", "s3:PutObject"],
- "Resource": "arn:aws:s3:::awsexamplebucket1/*"
- }
- ]
-}`},
- {`{
- "Version": "2012-10-17",
- "Id": "S3PolicyId1",
- "Statement": [
- {
- "Sid": "statement1",
- "Effect": "Allow",
- "Principal": "*",
- "Action":"s3:GetObject",
- "Resource": "arn:aws:s3:::awsexamplebucket1/*",
- "Condition" : {
- "IpAddress" : {
- "aws:SourceIp": "192.0.2.0/24"
- },
- "NotIpAddress" : {
- "aws:SourceIp": "192.0.2.188/32"
- }
- }
- }
- ]
-}`},
- {`{
- "Version": "2012-10-17",
- "Statement": [
- {
- "Sid": "cross-account permission to user in your own account",
- "Effect": "Allow",
- "Principal": {
- "AWS": "arn:aws:iam::123456789012:user/Dave"
- },
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::awsexamplebucket1/*"
- },
- {
- "Sid": "Deny your user permission to upload object if copy source is not /bucket/folder",
- "Effect": "Deny",
- "Principal": {
- "AWS": "arn:aws:iam::123456789012:user/Dave"
- },
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::awsexamplebucket1/*",
- "Condition": {
- "StringNotLike": {
- "s3:x-amz-copy-source": "awsexamplebucket1/public/*"
- }
- }
- }
- ]
-}`},
- }
-
- for i, testCase := range testCases {
- var p Policy
- err := json.Unmarshal([]byte(testCase.policy), &p)
- if err != nil {
- t.Fatalf("case %v: unexpected error: %v", i+1, err)
- }
-
- var clonedPolicy Policy
- clonedPolicy = clonedPolicy.Merge(p)
-
- j, err := json.Marshal(clonedPolicy)
- if err != nil {
- t.Fatalf("case %v: unexpected error: %v", i+1, err)
- }
-
- err = json.Unmarshal(j, &clonedPolicy)
- if err != nil {
- t.Fatalf("case %v: unexpected error: %v", i+1, err)
- }
-
- if !clonedPolicy.Statements[0].Equals(p.Statements[0]) {
- t.Fatalf("case %v: different policy outcome", i+1)
- }
- }
-}
diff --git a/pkg/bucket/policy/principal.go b/pkg/bucket/policy/principal.go
deleted file mode 100644
index 732df7433..000000000
--- a/pkg/bucket/policy/principal.go
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package policy
-
-import (
- "encoding/json"
-
- "github.com/minio/minio-go/v7/pkg/set"
- "github.com/minio/pkg/wildcard"
-)
-
-// Principal - policy principal.
-type Principal struct {
- AWS set.StringSet
-}
-
-// IsValid - checks whether Principal is valid or not.
-func (p Principal) IsValid() bool {
- return len(p.AWS) != 0
-}
-
-// Equals - returns true if principals are equal.
-func (p Principal) Equals(pp Principal) bool {
- return p.AWS.Equals(pp.AWS)
-}
-
-// Intersection - returns principals available in both Principal.
-func (p Principal) Intersection(principal Principal) set.StringSet {
- return p.AWS.Intersection(principal.AWS)
-}
-
-// MarshalJSON - encodes Principal to JSON data.
-func (p Principal) MarshalJSON() ([]byte, error) {
- if !p.IsValid() {
- return nil, Errorf("invalid principal %v", p)
- }
-
- // subtype to avoid recursive call to MarshalJSON()
- type subPrincipal Principal
- sp := subPrincipal(p)
- return json.Marshal(sp)
-}
-
-// Match - matches given principal is wildcard matching with Principal.
-func (p Principal) Match(principal string) bool {
- for _, pattern := range p.AWS.ToSlice() {
- if wildcard.MatchSimple(pattern, principal) {
- return true
- }
- }
-
- return false
-}
-
-// UnmarshalJSON - decodes JSON data to Principal.
-func (p *Principal) UnmarshalJSON(data []byte) error {
- // subtype to avoid recursive call to UnmarshalJSON()
- type subPrincipal Principal
- var sp subPrincipal
-
- if err := json.Unmarshal(data, &sp); err != nil {
- var s string
- if err = json.Unmarshal(data, &s); err != nil {
- return err
- }
-
- if s != "*" {
- return Errorf("invalid principal '%v'", s)
- }
-
- sp.AWS = set.CreateStringSet("*")
- }
-
- *p = Principal(sp)
-
- return nil
-}
-
-// Clone clones Principal structure
-func (p Principal) Clone() Principal {
- return NewPrincipal(p.AWS.ToSlice()...)
-
-}
-
-// NewPrincipal - creates new Principal.
-func NewPrincipal(principals ...string) Principal {
- return Principal{AWS: set.CreateStringSet(principals...)}
-}
diff --git a/pkg/bucket/policy/principal_test.go b/pkg/bucket/policy/principal_test.go
deleted file mode 100644
index eb76db635..000000000
--- a/pkg/bucket/policy/principal_test.go
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package policy
-
-import (
- "encoding/json"
- "reflect"
- "testing"
-
- "github.com/minio/minio-go/v7/pkg/set"
-)
-
-func TestPrincipalIsValid(t *testing.T) {
- testCases := []struct {
- principal Principal
- expectedResult bool
- }{
- {NewPrincipal("*"), true},
- {NewPrincipal("arn:aws:iam::AccountNumber:root"), true},
- {NewPrincipal(), false},
- }
-
- for i, testCase := range testCases {
- result := testCase.principal.IsValid()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestPrincipalIntersection(t *testing.T) {
- testCases := []struct {
- principal Principal
- principalToIntersect Principal
- expectedResult set.StringSet
- }{
- {NewPrincipal("*"), NewPrincipal("*"), set.CreateStringSet("*")},
- {NewPrincipal("arn:aws:iam::AccountNumber:root"), NewPrincipal("arn:aws:iam::AccountNumber:myuser"), set.CreateStringSet()},
- {NewPrincipal(), NewPrincipal("*"), set.CreateStringSet()},
- }
-
- for i, testCase := range testCases {
- result := testCase.principal.Intersection(testCase.principalToIntersect)
-
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestPrincipalMarshalJSON(t *testing.T) {
- testCases := []struct {
- principal Principal
- expectedResult []byte
- expectErr bool
- }{
- {NewPrincipal("*"), []byte(`{"AWS":["*"]}`), false},
- {NewPrincipal("arn:aws:iam::AccountNumber:*"), []byte(`{"AWS":["arn:aws:iam::AccountNumber:*"]}`), false},
- {NewPrincipal(), nil, true},
- }
-
- for i, testCase := range testCases {
- result, err := json.Marshal(testCase.principal)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, string(testCase.expectedResult), string(result))
- }
- }
- }
-}
-
-func TestPrincipalMatch(t *testing.T) {
- testCases := []struct {
- principals Principal
- principal string
- expectedResult bool
- }{
- {NewPrincipal("*"), "AccountNumber", true},
- {NewPrincipal("arn:aws:iam::*"), "arn:aws:iam::AccountNumber:root", true},
- {NewPrincipal("arn:aws:iam::AccountNumber:*"), "arn:aws:iam::TestAccountNumber:root", false},
- }
-
- for i, testCase := range testCases {
- result := testCase.principals.Match(testCase.principal)
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestPrincipalUnmarshalJSON(t *testing.T) {
- testCases := []struct {
- data []byte
- expectedResult Principal
- expectErr bool
- }{
- {[]byte(`"*"`), NewPrincipal("*"), false},
- {[]byte(`{"AWS": "*"}`), NewPrincipal("*"), false},
- {[]byte(`{"AWS": "arn:aws:iam::AccountNumber:*"}`), NewPrincipal("arn:aws:iam::AccountNumber:*"), false},
- {[]byte(`"arn:aws:iam::AccountNumber:*"`), NewPrincipal(), true},
- {[]byte(`["arn:aws:iam::AccountNumber:*", "arn:aws:iam:AnotherAccount:*"]`), NewPrincipal(), true},
- }
-
- for i, testCase := range testCases {
- var result Principal
- err := json.Unmarshal(testCase.data, &result)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
diff --git a/pkg/bucket/policy/resource.go b/pkg/bucket/policy/resource.go
deleted file mode 100644
index 07df24276..000000000
--- a/pkg/bucket/policy/resource.go
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package policy
-
-import (
- "encoding/json"
- "strings"
-
- "github.com/minio/minio/pkg/bucket/policy/condition"
- "github.com/minio/pkg/wildcard"
-)
-
-// ResourceARNPrefix - resource ARN prefix as per AWS S3 specification.
-const ResourceARNPrefix = "arn:aws:s3:::"
-
-// Resource - resource in policy statement.
-type Resource struct {
- BucketName string
- Pattern string
-}
-
-func (r Resource) isBucketPattern() bool {
- return !strings.Contains(r.Pattern, "/")
-}
-
-func (r Resource) isObjectPattern() bool {
- return strings.Contains(r.Pattern, "/") || strings.Contains(r.BucketName, "*")
-}
-
-// IsValid - checks whether Resource is valid or not.
-func (r Resource) IsValid() bool {
- return r.BucketName != "" && r.Pattern != ""
-}
-
-// Match - matches object name with resource pattern.
-func (r Resource) Match(resource string, conditionValues map[string][]string) bool {
- pattern := r.Pattern
- for _, key := range condition.CommonKeys {
- // Empty values are not supported for policy variables.
- if rvalues, ok := conditionValues[key.Name()]; ok && rvalues[0] != "" {
- pattern = strings.Replace(pattern, key.VarName(), rvalues[0], -1)
- }
- }
-
- return wildcard.Match(pattern, resource)
-}
-
-// MarshalJSON - encodes Resource to JSON data.
-func (r Resource) MarshalJSON() ([]byte, error) {
- if !r.IsValid() {
- return nil, Errorf("invalid resource %v", r)
- }
-
- return json.Marshal(r.String())
-}
-
-func (r Resource) String() string {
- return ResourceARNPrefix + r.Pattern
-}
-
-// UnmarshalJSON - decodes JSON data to Resource.
-func (r *Resource) UnmarshalJSON(data []byte) error {
- var s string
- if err := json.Unmarshal(data, &s); err != nil {
- return err
- }
-
- parsedResource, err := parseResource(s)
- if err != nil {
- return err
- }
-
- *r = parsedResource
-
- return nil
-}
-
-// Validate - validates Resource is for given bucket or not.
-func (r Resource) Validate(bucketName string) error {
- if !r.IsValid() {
- return Errorf("invalid resource")
- }
-
- if !wildcard.Match(r.BucketName, bucketName) {
- return Errorf("bucket name does not match")
- }
-
- return nil
-}
-
-// parseResource - parses string to Resource.
-func parseResource(s string) (Resource, error) {
- if !strings.HasPrefix(s, ResourceARNPrefix) {
- return Resource{}, Errorf("invalid resource '%v'", s)
- }
-
- pattern := strings.TrimPrefix(s, ResourceARNPrefix)
- tokens := strings.SplitN(pattern, "/", 2)
- bucketName := tokens[0]
- if bucketName == "" {
- return Resource{}, Errorf("invalid resource format '%v'", s)
- }
-
- return Resource{
- BucketName: bucketName,
- Pattern: pattern,
- }, nil
-}
-
-// NewResource - creates new resource.
-func NewResource(bucketName, keyName string) Resource {
- pattern := bucketName
- if keyName != "" {
- if !strings.HasPrefix(keyName, "/") {
- pattern += "/"
- }
-
- pattern += keyName
- }
-
- return Resource{
- BucketName: bucketName,
- Pattern: pattern,
- }
-}
diff --git a/pkg/bucket/policy/resource_test.go b/pkg/bucket/policy/resource_test.go
deleted file mode 100644
index a780bf4bf..000000000
--- a/pkg/bucket/policy/resource_test.go
+++ /dev/null
@@ -1,222 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package policy
-
-import (
- "encoding/json"
- "reflect"
- "testing"
-)
-
-func TestResourceIsBucketPattern(t *testing.T) {
- testCases := []struct {
- resource Resource
- expectedResult bool
- }{
- {NewResource("*", ""), true},
- {NewResource("mybucket", ""), true},
- {NewResource("mybucket*", ""), true},
- {NewResource("mybucket?0", ""), true},
- {NewResource("", "*"), false},
- {NewResource("*", "*"), false},
- {NewResource("mybucket", "*"), false},
- {NewResource("mybucket*", "/myobject"), false},
- {NewResource("mybucket?0", "/2010/photos/*"), false},
- }
-
- for i, testCase := range testCases {
- result := testCase.resource.isBucketPattern()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestResourceIsObjectPattern(t *testing.T) {
- testCases := []struct {
- resource Resource
- expectedResult bool
- }{
- {NewResource("*", ""), true},
- {NewResource("mybucket*", ""), true},
- {NewResource("", "*"), true},
- {NewResource("*", "*"), true},
- {NewResource("mybucket", "*"), true},
- {NewResource("mybucket*", "/myobject"), true},
- {NewResource("mybucket?0", "/2010/photos/*"), true},
- {NewResource("mybucket", ""), false},
- {NewResource("mybucket?0", ""), false},
- }
-
- for i, testCase := range testCases {
- result := testCase.resource.isObjectPattern()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestResourceIsValid(t *testing.T) {
- testCases := []struct {
- resource Resource
- expectedResult bool
- }{
- {NewResource("*", ""), true},
- {NewResource("mybucket*", ""), true},
- {NewResource("*", "*"), true},
- {NewResource("mybucket", "*"), true},
- {NewResource("mybucket*", "/myobject"), true},
- {NewResource("mybucket?0", "/2010/photos/*"), true},
- {NewResource("mybucket", ""), true},
- {NewResource("mybucket?0", ""), true},
- {NewResource("", ""), false},
- {NewResource("", "*"), false},
- }
-
- for i, testCase := range testCases {
- result := testCase.resource.IsValid()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestResourceMatch(t *testing.T) {
- testCases := []struct {
- resource Resource
- objectName string
- expectedResult bool
- }{
- {NewResource("*", ""), "mybucket", true},
- {NewResource("*", ""), "mybucket/myobject", true},
- {NewResource("mybucket*", ""), "mybucket", true},
- {NewResource("mybucket*", ""), "mybucket/myobject", true},
- {NewResource("", "*"), "/myobject", true},
- {NewResource("*", "*"), "mybucket/myobject", true},
- {NewResource("mybucket", "*"), "mybucket/myobject", true},
- {NewResource("mybucket*", "/myobject"), "mybucket/myobject", true},
- {NewResource("mybucket*", "/myobject"), "mybucket100/myobject", true},
- {NewResource("mybucket?0", "/2010/photos/*"), "mybucket20/2010/photos/1.jpg", true},
- {NewResource("mybucket", ""), "mybucket", true},
- {NewResource("mybucket?0", ""), "mybucket30", true},
- {NewResource("", "*"), "mybucket/myobject", false},
- {NewResource("*", "*"), "mybucket", false},
- {NewResource("mybucket", "*"), "mybucket10/myobject", false},
- {NewResource("mybucket?0", "/2010/photos/*"), "mybucket0/2010/photos/1.jpg", false},
- {NewResource("mybucket", ""), "mybucket/myobject", false},
- }
-
- for i, testCase := range testCases {
- result := testCase.resource.Match(testCase.objectName, nil)
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestResourceMarshalJSON(t *testing.T) {
- testCases := []struct {
- resource Resource
- expectedResult []byte
- expectErr bool
- }{
- {NewResource("*", ""), []byte(`"arn:aws:s3:::*"`), false},
- {NewResource("mybucket*", ""), []byte(`"arn:aws:s3:::mybucket*"`), false},
- {NewResource("mybucket", ""), []byte(`"arn:aws:s3:::mybucket"`), false},
- {NewResource("*", "*"), []byte(`"arn:aws:s3:::*/*"`), false},
- {NewResource("mybucket", "*"), []byte(`"arn:aws:s3:::mybucket/*"`), false},
- {NewResource("mybucket*", "myobject"), []byte(`"arn:aws:s3:::mybucket*/myobject"`), false},
- {NewResource("mybucket?0", "/2010/photos/*"), []byte(`"arn:aws:s3:::mybucket?0/2010/photos/*"`), false},
- {Resource{}, nil, true},
- {NewResource("", "*"), nil, true},
- }
-
- for i, testCase := range testCases {
- result, err := json.Marshal(testCase.resource)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v", i+1, string(testCase.expectedResult), string(result))
- }
- }
- }
-}
-
-func TestResourceUnmarshalJSON(t *testing.T) {
- testCases := []struct {
- data []byte
- expectedResult Resource
- expectErr bool
- }{
- {[]byte(`"arn:aws:s3:::*"`), NewResource("*", ""), false},
- {[]byte(`"arn:aws:s3:::mybucket*"`), NewResource("mybucket*", ""), false},
- {[]byte(`"arn:aws:s3:::mybucket"`), NewResource("mybucket", ""), false},
- {[]byte(`"arn:aws:s3:::*/*"`), NewResource("*", "*"), false},
- {[]byte(`"arn:aws:s3:::mybucket/*"`), NewResource("mybucket", "*"), false},
- {[]byte(`"arn:aws:s3:::mybucket*/myobject"`), NewResource("mybucket*", "myobject"), false},
- {[]byte(`"arn:aws:s3:::mybucket?0/2010/photos/*"`), NewResource("mybucket?0", "/2010/photos/*"), false},
- {[]byte(`"mybucket/myobject*"`), Resource{}, true},
- {[]byte(`"arn:aws:s3:::/*"`), Resource{}, true},
- }
-
- for i, testCase := range testCases {
- var result Resource
- err := json.Unmarshal(testCase.data, &result)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
-
-func TestResourceValidate(t *testing.T) {
- testCases := []struct {
- resource Resource
- bucketName string
- expectErr bool
- }{
- {NewResource("mybucket", "/myobject*"), "mybucket", false},
- {NewResource("", "/myobject*"), "yourbucket", true},
- {NewResource("mybucket", "/myobject*"), "yourbucket", true},
- }
-
- for i, testCase := range testCases {
- err := testCase.resource.Validate(testCase.bucketName)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
- }
-}
diff --git a/pkg/bucket/policy/resourceset.go b/pkg/bucket/policy/resourceset.go
deleted file mode 100644
index 1c37c7d79..000000000
--- a/pkg/bucket/policy/resourceset.go
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package policy
-
-import (
- "encoding/json"
- "fmt"
- "sort"
-
- "github.com/minio/minio-go/v7/pkg/set"
-)
-
-// ResourceSet - set of resources in policy statement.
-type ResourceSet map[Resource]struct{}
-
-// bucketResourceExists - checks if at least one bucket resource exists in the set.
-func (resourceSet ResourceSet) bucketResourceExists() bool {
- for resource := range resourceSet {
- if resource.isBucketPattern() {
- return true
- }
- }
-
- return false
-}
-
-// objectResourceExists - checks if at least one object resource exists in the set.
-func (resourceSet ResourceSet) objectResourceExists() bool {
- for resource := range resourceSet {
- if resource.isObjectPattern() {
- return true
- }
- }
-
- return false
-}
-
-// Add - adds resource to resource set.
-func (resourceSet ResourceSet) Add(resource Resource) {
- resourceSet[resource] = struct{}{}
-}
-
-// Equals - checks whether given resource set is equal to current resource set or not.
-func (resourceSet ResourceSet) Equals(sresourceSet ResourceSet) bool {
- // If length of set is not equal to length of given set, the
- // set is not equal to given set.
- if len(resourceSet) != len(sresourceSet) {
- return false
- }
-
- // As both sets are equal in length, check each elements are equal.
- for k := range resourceSet {
- if _, ok := sresourceSet[k]; !ok {
- return false
- }
- }
-
- return true
-}
-
-// Intersection - returns resouces available in both ResourcsSet.
-func (resourceSet ResourceSet) Intersection(sset ResourceSet) ResourceSet {
- nset := NewResourceSet()
- for k := range resourceSet {
- if _, ok := sset[k]; ok {
- nset.Add(k)
- }
- }
-
- return nset
-}
-
-// MarshalJSON - encodes ResourceSet to JSON data.
-func (resourceSet ResourceSet) MarshalJSON() ([]byte, error) {
- if len(resourceSet) == 0 {
- return nil, Errorf("empty resources not allowed")
- }
-
- resources := []Resource{}
- for resource := range resourceSet {
- resources = append(resources, resource)
- }
-
- return json.Marshal(resources)
-}
-
-// Match - matches object name with anyone of resource pattern in resource set.
-func (resourceSet ResourceSet) Match(resource string, conditionValues map[string][]string) bool {
- for r := range resourceSet {
- if r.Match(resource, conditionValues) {
- return true
- }
- }
-
- return false
-}
-
-func (resourceSet ResourceSet) String() string {
- resources := []string{}
- for resource := range resourceSet {
- resources = append(resources, resource.String())
- }
- sort.Strings(resources)
-
- return fmt.Sprintf("%v", resources)
-}
-
-// UnmarshalJSON - decodes JSON data to ResourceSet.
-func (resourceSet *ResourceSet) UnmarshalJSON(data []byte) error {
- var sset set.StringSet
- if err := json.Unmarshal(data, &sset); err != nil {
- return err
- }
-
- *resourceSet = make(ResourceSet)
- for _, s := range sset.ToSlice() {
- resource, err := parseResource(s)
- if err != nil {
- return err
- }
-
- if _, found := (*resourceSet)[resource]; found {
- return Errorf("duplicate resource '%v' found", s)
- }
-
- resourceSet.Add(resource)
- }
-
- return nil
-}
-
-// Validate - validates ResourceSet is for given bucket or not.
-func (resourceSet ResourceSet) Validate(bucketName string) error {
- for resource := range resourceSet {
- if err := resource.Validate(bucketName); err != nil {
- return err
- }
- }
-
- return nil
-}
-
-// ToSlice - returns slice of resources from the resource set.
-func (resourceSet ResourceSet) ToSlice() []Resource {
- resources := []Resource{}
- for resource := range resourceSet {
- resources = append(resources, resource)
- }
-
- return resources
-}
-
-// Clone clones ResourceSet structure
-func (resourceSet ResourceSet) Clone() ResourceSet {
- return NewResourceSet(resourceSet.ToSlice()...)
-}
-
-// NewResourceSet - creates new resource set.
-func NewResourceSet(resources ...Resource) ResourceSet {
- resourceSet := make(ResourceSet)
- for _, resource := range resources {
- resourceSet.Add(resource)
- }
-
- return resourceSet
-}
diff --git a/pkg/bucket/policy/resourceset_test.go b/pkg/bucket/policy/resourceset_test.go
deleted file mode 100644
index 8e74f805c..000000000
--- a/pkg/bucket/policy/resourceset_test.go
+++ /dev/null
@@ -1,241 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package policy
-
-import (
- "encoding/json"
- "reflect"
- "testing"
-)
-
-func TestResourceSetBucketResourceExists(t *testing.T) {
- testCases := []struct {
- resourceSet ResourceSet
- expectedResult bool
- }{
- {NewResourceSet(NewResource("*", "")), true},
- {NewResourceSet(NewResource("mybucket", "")), true},
- {NewResourceSet(NewResource("mybucket*", "")), true},
- {NewResourceSet(NewResource("mybucket?0", "")), true},
- {NewResourceSet(NewResource("mybucket", "/2010/photos/*"), NewResource("mybucket", "")), true},
- {NewResourceSet(NewResource("", "*")), false},
- {NewResourceSet(NewResource("*", "*")), false},
- {NewResourceSet(NewResource("mybucket", "*")), false},
- {NewResourceSet(NewResource("mybucket*", "/myobject")), false},
- {NewResourceSet(NewResource("mybucket?0", "/2010/photos/*")), false},
- }
-
- for i, testCase := range testCases {
- result := testCase.resourceSet.bucketResourceExists()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestResourceSetObjectResourceExists(t *testing.T) {
- testCases := []struct {
- resourceSet ResourceSet
- expectedResult bool
- }{
- {NewResourceSet(NewResource("*", "")), true},
- {NewResourceSet(NewResource("mybucket*", "")), true},
- {NewResourceSet(NewResource("", "*")), true},
- {NewResourceSet(NewResource("*", "*")), true},
- {NewResourceSet(NewResource("mybucket", "*")), true},
- {NewResourceSet(NewResource("mybucket*", "/myobject")), true},
- {NewResourceSet(NewResource("mybucket?0", "/2010/photos/*")), true},
- {NewResourceSet(NewResource("mybucket", ""), NewResource("mybucket", "/2910/photos/*")), true},
- {NewResourceSet(NewResource("mybucket", "")), false},
- {NewResourceSet(NewResource("mybucket?0", "")), false},
- }
-
- for i, testCase := range testCases {
- result := testCase.resourceSet.objectResourceExists()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestResourceSetAdd(t *testing.T) {
- testCases := []struct {
- resourceSet ResourceSet
- resource Resource
- expectedResult ResourceSet
- }{
- {NewResourceSet(), NewResource("mybucket", "/myobject*"),
- NewResourceSet(NewResource("mybucket", "/myobject*"))},
- {NewResourceSet(NewResource("mybucket", "/myobject*")),
- NewResource("mybucket", "/yourobject*"),
- NewResourceSet(NewResource("mybucket", "/myobject*"),
- NewResource("mybucket", "/yourobject*"))},
- {NewResourceSet(NewResource("mybucket", "/myobject*")),
- NewResource("mybucket", "/myobject*"),
- NewResourceSet(NewResource("mybucket", "/myobject*"))},
- }
-
- for i, testCase := range testCases {
- testCase.resourceSet.Add(testCase.resource)
-
- if !reflect.DeepEqual(testCase.resourceSet, testCase.expectedResult) {
- t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectedResult, testCase.resourceSet)
- }
- }
-}
-
-func TestResourceSetIntersection(t *testing.T) {
- testCases := []struct {
- set ResourceSet
- setToIntersect ResourceSet
- expectedResult ResourceSet
- }{
- {NewResourceSet(), NewResourceSet(NewResource("mybucket", "/myobject*")), NewResourceSet()},
- {NewResourceSet(NewResource("mybucket", "/myobject*")), NewResourceSet(), NewResourceSet()},
- {NewResourceSet(NewResource("mybucket", "/myobject*")),
- NewResourceSet(NewResource("mybucket", "/myobject*"), NewResource("mybucket", "/yourobject*")),
- NewResourceSet(NewResource("mybucket", "/myobject*"))},
- }
-
- for i, testCase := range testCases {
- result := testCase.set.Intersection(testCase.setToIntersect)
-
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, testCase.set)
- }
- }
-}
-
-func TestResourceSetMarshalJSON(t *testing.T) {
- testCases := []struct {
- resoruceSet ResourceSet
- expectedResult []byte
- expectErr bool
- }{
- {NewResourceSet(NewResource("mybucket", "/myobject*")),
- []byte(`["arn:aws:s3:::mybucket/myobject*"]`), false},
- {NewResourceSet(NewResource("mybucket", "/photos/myobject*")),
- []byte(`["arn:aws:s3:::mybucket/photos/myobject*"]`), false},
- {NewResourceSet(), nil, true},
- }
-
- for i, testCase := range testCases {
- result, err := json.Marshal(testCase.resoruceSet)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v", i+1, string(testCase.expectedResult), string(result))
- }
- }
- }
-}
-
-func TestResourceSetMatch(t *testing.T) {
- testCases := []struct {
- resourceSet ResourceSet
- resource string
- expectedResult bool
- }{
- {NewResourceSet(NewResource("*", "")), "mybucket", true},
- {NewResourceSet(NewResource("*", "")), "mybucket/myobject", true},
- {NewResourceSet(NewResource("mybucket*", "")), "mybucket", true},
- {NewResourceSet(NewResource("mybucket*", "")), "mybucket/myobject", true},
- {NewResourceSet(NewResource("", "*")), "/myobject", true},
- {NewResourceSet(NewResource("*", "*")), "mybucket/myobject", true},
- {NewResourceSet(NewResource("mybucket", "*")), "mybucket/myobject", true},
- {NewResourceSet(NewResource("mybucket*", "/myobject")), "mybucket/myobject", true},
- {NewResourceSet(NewResource("mybucket*", "/myobject")), "mybucket100/myobject", true},
- {NewResourceSet(NewResource("mybucket?0", "/2010/photos/*")), "mybucket20/2010/photos/1.jpg", true},
- {NewResourceSet(NewResource("mybucket", "")), "mybucket", true},
- {NewResourceSet(NewResource("mybucket?0", "")), "mybucket30", true},
- {NewResourceSet(NewResource("mybucket?0", "/2010/photos/*"),
- NewResource("mybucket", "/2010/photos/*")), "mybucket/2010/photos/1.jpg", true},
- {NewResourceSet(NewResource("", "*")), "mybucket/myobject", false},
- {NewResourceSet(NewResource("*", "*")), "mybucket", false},
- {NewResourceSet(NewResource("mybucket", "*")), "mybucket10/myobject", false},
- {NewResourceSet(NewResource("mybucket", "")), "mybucket/myobject", false},
- {NewResourceSet(), "mybucket/myobject", false},
- }
-
- for i, testCase := range testCases {
- result := testCase.resourceSet.Match(testCase.resource, nil)
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestResourceSetUnmarshalJSON(t *testing.T) {
- testCases := []struct {
- data []byte
- expectedResult ResourceSet
- expectErr bool
- }{
- {[]byte(`"arn:aws:s3:::mybucket/myobject*"`),
- NewResourceSet(NewResource("mybucket", "/myobject*")), false},
- {[]byte(`"arn:aws:s3:::mybucket/photos/myobject*"`),
- NewResourceSet(NewResource("mybucket", "/photos/myobject*")), false},
- {[]byte(`"arn:aws:s3:::mybucket"`), NewResourceSet(NewResource("mybucket", "")), false},
- {[]byte(`"mybucket/myobject*"`), nil, true},
- }
-
- for i, testCase := range testCases {
- var result ResourceSet
- err := json.Unmarshal(testCase.data, &result)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
-
-func TestResourceSetValidate(t *testing.T) {
- testCases := []struct {
- resourceSet ResourceSet
- bucketName string
- expectErr bool
- }{
- {NewResourceSet(NewResource("mybucket", "/myobject*")), "mybucket", false},
- {NewResourceSet(NewResource("", "/myobject*")), "yourbucket", true},
- {NewResourceSet(NewResource("mybucket", "/myobject*")), "yourbucket", true},
- }
-
- for i, testCase := range testCases {
- err := testCase.resourceSet.Validate(testCase.bucketName)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
- }
-}
diff --git a/pkg/bucket/policy/statement.go b/pkg/bucket/policy/statement.go
deleted file mode 100644
index 7614fcabc..000000000
--- a/pkg/bucket/policy/statement.go
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package policy
-
-import (
- "encoding/json"
- "strings"
-
- "github.com/minio/minio/pkg/bucket/policy/condition"
-)
-
-// Statement - policy statement.
-type Statement struct {
- SID ID `json:"Sid,omitempty"`
- Effect Effect `json:"Effect"`
- Principal Principal `json:"Principal"`
- Actions ActionSet `json:"Action"`
- Resources ResourceSet `json:"Resource"`
- Conditions condition.Functions `json:"Condition,omitempty"`
-}
-
-// Equals checks if two statements are equal
-func (statement Statement) Equals(st Statement) bool {
- if statement.Effect != st.Effect {
- return false
- }
- if !statement.Principal.Equals(st.Principal) {
- return false
- }
- if !statement.Actions.Equals(st.Actions) {
- return false
- }
- if !statement.Resources.Equals(st.Resources) {
- return false
- }
- if !statement.Conditions.Equals(st.Conditions) {
- return false
- }
- return true
-}
-
-// IsAllowed - checks given policy args is allowed to continue the Rest API.
-func (statement Statement) IsAllowed(args Args) bool {
- check := func() bool {
- if !statement.Principal.Match(args.AccountName) {
- return false
- }
-
- if !statement.Actions.Contains(args.Action) {
- return false
- }
-
- resource := args.BucketName
- if args.ObjectName != "" {
- if !strings.HasPrefix(args.ObjectName, "/") {
- resource += "/"
- }
-
- resource += args.ObjectName
- }
-
- if !statement.Resources.Match(resource, args.ConditionValues) {
- return false
- }
-
- return statement.Conditions.Evaluate(args.ConditionValues)
- }
-
- return statement.Effect.IsAllowed(check())
-}
-
-// isValid - checks whether statement is valid or not.
-func (statement Statement) isValid() error {
- if !statement.Effect.IsValid() {
- return Errorf("invalid Effect %v", statement.Effect)
- }
-
- if !statement.Principal.IsValid() {
- return Errorf("invalid Principal %v", statement.Principal)
- }
-
- if len(statement.Actions) == 0 {
- return Errorf("Action must not be empty")
- }
-
- if len(statement.Resources) == 0 {
- return Errorf("Resource must not be empty")
- }
-
- for action := range statement.Actions {
- if action.isObjectAction() {
- if !statement.Resources.objectResourceExists() {
- return Errorf("unsupported Resource found %v for action %v", statement.Resources, action)
- }
- } else {
- if !statement.Resources.bucketResourceExists() {
- return Errorf("unsupported Resource found %v for action %v", statement.Resources, action)
- }
- }
-
- keys := statement.Conditions.Keys()
- keyDiff := keys.Difference(actionConditionKeyMap[action])
- if !keyDiff.IsEmpty() {
- return Errorf("unsupported condition keys '%v' used for action '%v'", keyDiff, action)
- }
- }
-
- return nil
-}
-
-// MarshalJSON - encodes JSON data to Statement.
-func (statement Statement) MarshalJSON() ([]byte, error) {
- if err := statement.isValid(); err != nil {
- return nil, err
- }
-
- // subtype to avoid recursive call to MarshalJSON()
- type subStatement Statement
- ss := subStatement(statement)
- return json.Marshal(ss)
-}
-
-// UnmarshalJSON - decodes JSON data to Statement.
-func (statement *Statement) UnmarshalJSON(data []byte) error {
- // subtype to avoid recursive call to UnmarshalJSON()
- type subStatement Statement
- var ss subStatement
-
- if err := json.Unmarshal(data, &ss); err != nil {
- return err
- }
-
- s := Statement(ss)
- if err := s.isValid(); err != nil {
- return err
- }
-
- *statement = s
-
- return nil
-}
-
-// Validate - validates Statement is for given bucket or not.
-func (statement Statement) Validate(bucketName string) error {
- if err := statement.isValid(); err != nil {
- return err
- }
-
- return statement.Resources.Validate(bucketName)
-}
-
-// Clone clones Statement structure
-func (statement Statement) Clone() Statement {
- return NewStatement(statement.Effect, statement.Principal.Clone(),
- statement.Actions.Clone(), statement.Resources.Clone(), statement.Conditions.Clone())
-}
-
-// NewStatement - creates new statement.
-func NewStatement(effect Effect, principal Principal, actionSet ActionSet, resourceSet ResourceSet, conditions condition.Functions) Statement {
- return Statement{
- Effect: effect,
- Principal: principal,
- Actions: actionSet,
- Resources: resourceSet,
- Conditions: conditions,
- }
-}
diff --git a/pkg/bucket/policy/statement_test.go b/pkg/bucket/policy/statement_test.go
deleted file mode 100644
index 92b584b0a..000000000
--- a/pkg/bucket/policy/statement_test.go
+++ /dev/null
@@ -1,572 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package policy
-
-import (
- "encoding/json"
- "net"
- "reflect"
- "testing"
-
- "github.com/minio/minio/pkg/bucket/policy/condition"
-)
-
-func TestStatementIsAllowed(t *testing.T) {
- case1Statement := NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(GetBucketLocationAction, PutObjectAction),
- NewResourceSet(NewResource("*", "")),
- condition.NewFunctions(),
- )
-
- case2Statement := NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(GetObjectAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- )
-
- _, IPNet1, err := net.ParseCIDR("192.168.1.0/24")
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- func1, err := condition.NewIPAddressFunc(
- condition.AWSSourceIP,
- IPNet1,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Statement := NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(GetObjectAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(func1),
- )
-
- case4Statement := NewStatement(
- Deny,
- NewPrincipal("*"),
- NewActionSet(GetObjectAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(func1),
- )
-
- anonGetBucketLocationArgs := Args{
- AccountName: "Q3AM3UQ867SPQQA43P2F",
- Action: GetBucketLocationAction,
- BucketName: "mybucket",
- ConditionValues: map[string][]string{},
- }
-
- anonPutObjectActionArgs := Args{
- AccountName: "Q3AM3UQ867SPQQA43P2F",
- Action: PutObjectAction,
- BucketName: "mybucket",
- ConditionValues: map[string][]string{
- "x-amz-copy-source": {"mybucket/myobject"},
- "SourceIp": {"192.168.1.10"},
- },
- ObjectName: "myobject",
- }
-
- anonGetObjectActionArgs := Args{
- AccountName: "Q3AM3UQ867SPQQA43P2F",
- Action: GetObjectAction,
- BucketName: "mybucket",
- ConditionValues: map[string][]string{},
- ObjectName: "myobject",
- }
-
- getBucketLocationArgs := Args{
- AccountName: "Q3AM3UQ867SPQQA43P2F",
- Action: GetBucketLocationAction,
- BucketName: "mybucket",
- ConditionValues: map[string][]string{},
- IsOwner: true,
- }
-
- putObjectActionArgs := Args{
- AccountName: "Q3AM3UQ867SPQQA43P2F",
- Action: PutObjectAction,
- BucketName: "mybucket",
- ConditionValues: map[string][]string{
- "x-amz-copy-source": {"mybucket/myobject"},
- "SourceIp": {"192.168.1.10"},
- },
- IsOwner: true,
- ObjectName: "myobject",
- }
-
- getObjectActionArgs := Args{
- AccountName: "Q3AM3UQ867SPQQA43P2F",
- Action: GetObjectAction,
- BucketName: "mybucket",
- ConditionValues: map[string][]string{},
- IsOwner: true,
- ObjectName: "myobject",
- }
-
- testCases := []struct {
- statement Statement
- args Args
- expectedResult bool
- }{
- {case1Statement, anonGetBucketLocationArgs, true},
- {case1Statement, anonPutObjectActionArgs, true},
- {case1Statement, anonGetObjectActionArgs, false},
- {case1Statement, getBucketLocationArgs, true},
- {case1Statement, putObjectActionArgs, true},
- {case1Statement, getObjectActionArgs, false},
-
- {case2Statement, anonGetBucketLocationArgs, false},
- {case2Statement, anonPutObjectActionArgs, true},
- {case2Statement, anonGetObjectActionArgs, true},
- {case2Statement, getBucketLocationArgs, false},
- {case2Statement, putObjectActionArgs, true},
- {case2Statement, getObjectActionArgs, true},
-
- {case3Statement, anonGetBucketLocationArgs, false},
- {case3Statement, anonPutObjectActionArgs, true},
- {case3Statement, anonGetObjectActionArgs, false},
- {case3Statement, getBucketLocationArgs, false},
- {case3Statement, putObjectActionArgs, true},
- {case3Statement, getObjectActionArgs, false},
-
- {case4Statement, anonGetBucketLocationArgs, true},
- {case4Statement, anonPutObjectActionArgs, false},
- {case4Statement, anonGetObjectActionArgs, true},
- {case4Statement, getBucketLocationArgs, true},
- {case4Statement, putObjectActionArgs, false},
- {case4Statement, getObjectActionArgs, true},
- }
-
- for i, testCase := range testCases {
- result := testCase.statement.IsAllowed(testCase.args)
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestStatementIsValid(t *testing.T) {
- _, IPNet1, err := net.ParseCIDR("192.168.1.0/24")
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- func1, err := condition.NewIPAddressFunc(
- condition.AWSSourceIP,
- IPNet1,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- func2, err := condition.NewStringEqualsFunc(
- condition.S3XAmzCopySource,
- "mybucket/myobject",
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- statement Statement
- expectErr bool
- }{
- // Invalid effect error.
- {NewStatement(
- Effect("foo"),
- NewPrincipal("*"),
- NewActionSet(GetBucketLocationAction, PutObjectAction),
- NewResourceSet(NewResource("*", "")),
- condition.NewFunctions(),
- ), true},
- // Invalid principal error.
- {NewStatement(
- Allow,
- NewPrincipal(),
- NewActionSet(GetBucketLocationAction, PutObjectAction),
- NewResourceSet(NewResource("*", "")),
- condition.NewFunctions(),
- ), true},
- // Empty actions error.
- {NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(),
- NewResourceSet(NewResource("*", "")),
- condition.NewFunctions(),
- ), true},
- // Empty resources error.
- {NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(GetBucketLocationAction, PutObjectAction),
- NewResourceSet(),
- condition.NewFunctions(),
- ), true},
- // Unsupported resource found for object action.
- {NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(GetBucketLocationAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "")),
- condition.NewFunctions(),
- ), true},
- // Unsupported resource found for bucket action.
- {NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(GetBucketLocationAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "myobject*")),
- condition.NewFunctions(),
- ), true},
- // Unsupported condition key for action.
- {NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(GetObjectAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "myobject*")),
- condition.NewFunctions(func1, func2),
- ), true},
- {NewStatement(
- Deny,
- NewPrincipal("*"),
- NewActionSet(GetObjectAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "myobject*")),
- condition.NewFunctions(func1),
- ), false},
- }
-
- for i, testCase := range testCases {
- err := testCase.statement.isValid()
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
- }
-}
-
-func TestStatementMarshalJSON(t *testing.T) {
- case1Statement := NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- )
- case1Statement.SID = "SomeId1"
- case1Data := []byte(`{"Sid":"SomeId1","Effect":"Allow","Principal":{"AWS":["*"]},"Action":["s3:PutObject"],"Resource":["arn:aws:s3:::mybucket/myobject*"]}`)
-
- func1, err := condition.NewNullFunc(
- condition.S3XAmzCopySource,
- true,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- case2Statement := NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(func1),
- )
- case2Data := []byte(`{"Effect":"Allow","Principal":{"AWS":["*"]},"Action":["s3:PutObject"],"Resource":["arn:aws:s3:::mybucket/myobject*"],"Condition":{"Null":{"s3:x-amz-copy-source":[true]}}}`)
-
- func2, err := condition.NewNullFunc(
- condition.S3XAmzServerSideEncryption,
- false,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- case3Statement := NewStatement(
- Deny,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(func2),
- )
- case3Data := []byte(`{"Effect":"Deny","Principal":{"AWS":["*"]},"Action":["s3:PutObject"],"Resource":["arn:aws:s3:::mybucket/myobject*"],"Condition":{"Null":{"s3:x-amz-server-side-encryption":[false]}}}`)
-
- case4Statement := NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(GetObjectAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "myobject*")),
- condition.NewFunctions(func1, func2),
- )
-
- testCases := []struct {
- statement Statement
- expectedResult []byte
- expectErr bool
- }{
- {case1Statement, case1Data, false},
- {case2Statement, case2Data, false},
- {case3Statement, case3Data, false},
- // Invalid statement error.
- {case4Statement, nil, true},
- }
-
- for i, testCase := range testCases {
- result, err := json.Marshal(testCase.statement)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v", i+1, string(testCase.expectedResult), string(result))
- }
- }
- }
-}
-
-func TestStatementUnmarshalJSON(t *testing.T) {
- case1Data := []byte(`{
- "Sid": "SomeId1",
- "Effect": "Allow",
- "Principal": "*",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
-}`)
- case1Statement := NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- )
- case1Statement.SID = "SomeId1"
-
- case2Data := []byte(`{
- "Effect": "Allow",
- "Principal": "*",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*",
- "Condition": {
- "Null": {
- "s3:x-amz-copy-source": true
- }
- }
-}`)
- func1, err := condition.NewNullFunc(
- condition.S3XAmzCopySource,
- true,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- case2Statement := NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(func1),
- )
-
- case3Data := []byte(`{
- "Effect": "Deny",
- "Principal": {
- "AWS": "*"
- },
- "Action": [
- "s3:PutObject",
- "s3:GetObject"
- ],
- "Resource": "arn:aws:s3:::mybucket/myobject*",
- "Condition": {
- "Null": {
- "s3:x-amz-server-side-encryption": "false"
- }
- }
-}`)
- func2, err := condition.NewNullFunc(
- condition.S3XAmzServerSideEncryption,
- false,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- case3Statement := NewStatement(
- Deny,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction, GetObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(func2),
- )
-
- case4Data := []byte(`{
- "Effect": "Allow",
- "Principal": "Q3AM3UQ867SPQQA43P2F",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
-}`)
-
- case5Data := []byte(`{
- "Principal": "*",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
-}`)
-
- case6Data := []byte(`{
- "Effect": "Allow",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
-}`)
-
- case7Data := []byte(`{
- "Effect": "Allow",
- "Principal": "*",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
-}`)
-
- case8Data := []byte(`{
- "Effect": "Allow",
- "Principal": "*",
- "Action": "s3:PutObject"
-}`)
-
- case9Data := []byte(`{
- "Effect": "Allow",
- "Principal": "*",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*",
- "Condition": {
- }
-}`)
-
- case10Data := []byte(`{
- "Effect": "Deny",
- "Principal": {
- "AWS": "*"
- },
- "Action": [
- "s3:PutObject",
- "s3:GetObject"
- ],
- "Resource": "arn:aws:s3:::mybucket/myobject*",
- "Condition": {
- "StringEquals": {
- "s3:x-amz-copy-source": "yourbucket/myobject*"
- }
- }
-}`)
-
- testCases := []struct {
- data []byte
- expectedResult Statement
- expectErr bool
- }{
- {case1Data, case1Statement, false},
- {case2Data, case2Statement, false},
- {case3Data, case3Statement, false},
- // JSON unmarshaling error.
- {case4Data, Statement{}, true},
- // Invalid effect error.
- {case5Data, Statement{}, true},
- // empty principal error.
- {case6Data, Statement{}, true},
- // Empty action error.
- {case7Data, Statement{}, true},
- // Empty resource error.
- {case8Data, Statement{}, true},
- // Empty condition error.
- {case9Data, Statement{}, true},
- // Unsupported condition key error.
- {case10Data, Statement{}, true},
- }
-
- for i, testCase := range testCases {
- var result Statement
- err := json.Unmarshal(testCase.data, &result)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
-
-func TestStatementValidate(t *testing.T) {
- case1Statement := NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- )
-
- func1, err := condition.NewNullFunc(
- condition.S3XAmzCopySource,
- true,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- func2, err := condition.NewNullFunc(
- condition.S3XAmzServerSideEncryption,
- false,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- case2Statement := NewStatement(
- Allow,
- NewPrincipal("*"),
- NewActionSet(GetObjectAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "myobject*")),
- condition.NewFunctions(func1, func2),
- )
-
- testCases := []struct {
- statement Statement
- bucketName string
- expectErr bool
- }{
- {case1Statement, "mybucket", false},
- {case2Statement, "mybucket", true},
- {case1Statement, "yourbucket", true},
- }
-
- for i, testCase := range testCases {
- err := testCase.statement.Validate(testCase.bucketName)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
- }
-}
diff --git a/pkg/iam/policy/action.go b/pkg/iam/policy/action.go
deleted file mode 100644
index af2652565..000000000
--- a/pkg/iam/policy/action.go
+++ /dev/null
@@ -1,439 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package iampolicy
-
-import (
- "github.com/minio/minio/pkg/bucket/policy/condition"
- "github.com/minio/pkg/wildcard"
-)
-
-// Action - policy action.
-// Refer https://docs.aws.amazon.com/IAM/latest/UserGuide/list_amazons3.html
-// for more information about available actions.
-type Action string
-
-const (
- // AbortMultipartUploadAction - AbortMultipartUpload Rest API action.
- AbortMultipartUploadAction Action = "s3:AbortMultipartUpload"
-
- // CreateBucketAction - CreateBucket Rest API action.
- CreateBucketAction = "s3:CreateBucket"
-
- // DeleteBucketAction - DeleteBucket Rest API action.
- DeleteBucketAction = "s3:DeleteBucket"
-
- // ForceDeleteBucketAction - DeleteBucket Rest API action when x-minio-force-delete flag
- // is specified.
- ForceDeleteBucketAction = "s3:ForceDeleteBucket"
-
- // DeleteBucketPolicyAction - DeleteBucketPolicy Rest API action.
- DeleteBucketPolicyAction = "s3:DeleteBucketPolicy"
-
- // DeleteObjectAction - DeleteObject Rest API action.
- DeleteObjectAction = "s3:DeleteObject"
-
- // GetBucketLocationAction - GetBucketLocation Rest API action.
- GetBucketLocationAction = "s3:GetBucketLocation"
-
- // GetBucketNotificationAction - GetBucketNotification Rest API action.
- GetBucketNotificationAction = "s3:GetBucketNotification"
-
- // GetBucketPolicyAction - GetBucketPolicy Rest API action.
- GetBucketPolicyAction = "s3:GetBucketPolicy"
-
- // GetObjectAction - GetObject Rest API action.
- GetObjectAction = "s3:GetObject"
-
- // HeadBucketAction - HeadBucket Rest API action. This action is unused in minio.
- HeadBucketAction = "s3:HeadBucket"
-
- // ListAllMyBucketsAction - ListAllMyBuckets (List buckets) Rest API action.
- ListAllMyBucketsAction = "s3:ListAllMyBuckets"
-
- // ListBucketAction - ListBucket Rest API action.
- ListBucketAction = "s3:ListBucket"
-
- // GetBucketPolicyStatusAction - Retrieves the policy status for a bucket.
- GetBucketPolicyStatusAction = "s3:GetBucketPolicyStatus"
-
- // ListBucketVersionsAction - ListBucketVersions Rest API action.
- ListBucketVersionsAction = "s3:ListBucketVersions"
-
- // ListBucketMultipartUploadsAction - ListMultipartUploads Rest API action.
- ListBucketMultipartUploadsAction = "s3:ListBucketMultipartUploads"
-
- // ListenNotificationAction - ListenNotification Rest API action.
- // This is MinIO extension.
- ListenNotificationAction = "s3:ListenNotification"
-
- // ListenBucketNotificationAction - ListenBucketNotification Rest API action.
- // This is MinIO extension.
- ListenBucketNotificationAction = "s3:ListenBucketNotification"
-
- // ListMultipartUploadPartsAction - ListParts Rest API action.
- ListMultipartUploadPartsAction = "s3:ListMultipartUploadParts"
-
- // PutBucketLifecycleAction - PutBucketLifecycle Rest API action.
- PutBucketLifecycleAction = "s3:PutLifecycleConfiguration"
-
- // GetBucketLifecycleAction - GetBucketLifecycle Rest API action.
- GetBucketLifecycleAction = "s3:GetLifecycleConfiguration"
-
- // PutBucketNotificationAction - PutObjectNotification Rest API action.
- PutBucketNotificationAction = "s3:PutBucketNotification"
-
- // PutBucketPolicyAction - PutBucketPolicy Rest API action.
- PutBucketPolicyAction = "s3:PutBucketPolicy"
-
- // PutObjectAction - PutObject Rest API action.
- PutObjectAction = "s3:PutObject"
-
- // DeleteObjectVersionAction - DeleteObjectVersion Rest API action.
- DeleteObjectVersionAction = "s3:DeleteObjectVersion"
-
- // DeleteObjectVersionTaggingAction - DeleteObjectVersionTagging Rest API action.
- DeleteObjectVersionTaggingAction = "s3:DeleteObjectVersionTagging"
-
- // GetObjectVersionAction - GetObjectVersionAction Rest API action.
- GetObjectVersionAction = "s3:GetObjectVersion"
-
- // GetObjectVersionTaggingAction - GetObjectVersionTagging Rest API action.
- GetObjectVersionTaggingAction = "s3:GetObjectVersionTagging"
-
- // PutObjectVersionTaggingAction - PutObjectVersionTagging Rest API action.
- PutObjectVersionTaggingAction = "s3:PutObjectVersionTagging"
-
- // BypassGovernanceRetentionAction - bypass governance retention for PutObjectRetention, PutObject and DeleteObject Rest API action.
- BypassGovernanceRetentionAction = "s3:BypassGovernanceRetention"
-
- // PutObjectRetentionAction - PutObjectRetention Rest API action.
- PutObjectRetentionAction = "s3:PutObjectRetention"
-
- // GetObjectRetentionAction - GetObjectRetention, GetObject, HeadObject Rest API action.
- GetObjectRetentionAction = "s3:GetObjectRetention"
-
- // GetObjectLegalHoldAction - GetObjectLegalHold, GetObject Rest API action.
- GetObjectLegalHoldAction = "s3:GetObjectLegalHold"
-
- // PutObjectLegalHoldAction - PutObjectLegalHold, PutObject Rest API action.
- PutObjectLegalHoldAction = "s3:PutObjectLegalHold"
-
- // GetBucketObjectLockConfigurationAction - GetBucketObjectLockConfiguration Rest API action
- GetBucketObjectLockConfigurationAction = "s3:GetBucketObjectLockConfiguration"
-
- // PutBucketObjectLockConfigurationAction - PutBucketObjectLockConfiguration Rest API action
- PutBucketObjectLockConfigurationAction = "s3:PutBucketObjectLockConfiguration"
-
- // GetBucketTaggingAction - GetBucketTagging Rest API action
- GetBucketTaggingAction = "s3:GetBucketTagging"
-
- // PutBucketTaggingAction - PutBucketTagging Rest API action
- PutBucketTaggingAction = "s3:PutBucketTagging"
-
- // GetObjectTaggingAction - Get Object Tags API action
- GetObjectTaggingAction = "s3:GetObjectTagging"
-
- // PutObjectTaggingAction - Put Object Tags API action
- PutObjectTaggingAction = "s3:PutObjectTagging"
-
- // DeleteObjectTaggingAction - Delete Object Tags API action
- DeleteObjectTaggingAction = "s3:DeleteObjectTagging"
-
- // PutBucketEncryptionAction - PutBucketEncryption REST API action
- PutBucketEncryptionAction = "s3:PutEncryptionConfiguration"
-
- // GetBucketEncryptionAction - GetBucketEncryption REST API action
- GetBucketEncryptionAction = "s3:GetEncryptionConfiguration"
-
- // PutBucketVersioningAction - PutBucketVersioning REST API action
- PutBucketVersioningAction = "s3:PutBucketVersioning"
-
- // GetBucketVersioningAction - GetBucketVersioning REST API action
- GetBucketVersioningAction = "s3:GetBucketVersioning"
- // GetReplicationConfigurationAction - GetReplicationConfiguration REST API action
- GetReplicationConfigurationAction = "s3:GetReplicationConfiguration"
- // PutReplicationConfigurationAction - PutReplicationConfiguration REST API action
- PutReplicationConfigurationAction = "s3:PutReplicationConfiguration"
-
- // ReplicateObjectAction - ReplicateObject REST API action
- ReplicateObjectAction = "s3:ReplicateObject"
-
- // ReplicateDeleteAction - ReplicateDelete REST API action
- ReplicateDeleteAction = "s3:ReplicateDelete"
-
- // ReplicateTagsAction - ReplicateTags REST API action
- ReplicateTagsAction = "s3:ReplicateTags"
-
- // GetObjectVersionForReplicationAction - GetObjectVersionForReplication REST API action
- GetObjectVersionForReplicationAction = "s3:GetObjectVersionForReplication"
-
- // AllActions - all API actions
- AllActions = "s3:*"
-)
-
-// List of all supported actions.
-var supportedActions = map[Action]struct{}{
- AbortMultipartUploadAction: {},
- CreateBucketAction: {},
- DeleteBucketAction: {},
- ForceDeleteBucketAction: {},
- DeleteBucketPolicyAction: {},
- DeleteObjectAction: {},
- GetBucketLocationAction: {},
- GetBucketNotificationAction: {},
- GetBucketPolicyAction: {},
- GetObjectAction: {},
- HeadBucketAction: {},
- ListAllMyBucketsAction: {},
- ListBucketAction: {},
- GetBucketPolicyStatusAction: {},
- ListBucketVersionsAction: {},
- ListBucketMultipartUploadsAction: {},
- ListenNotificationAction: {},
- ListenBucketNotificationAction: {},
- ListMultipartUploadPartsAction: {},
- PutBucketLifecycleAction: {},
- GetBucketLifecycleAction: {},
- PutBucketNotificationAction: {},
- PutBucketPolicyAction: {},
- PutObjectAction: {},
- BypassGovernanceRetentionAction: {},
- PutObjectRetentionAction: {},
- GetObjectRetentionAction: {},
- GetObjectLegalHoldAction: {},
- PutObjectLegalHoldAction: {},
- GetBucketObjectLockConfigurationAction: {},
- PutBucketObjectLockConfigurationAction: {},
- GetBucketTaggingAction: {},
- PutBucketTaggingAction: {},
- GetObjectVersionAction: {},
- GetObjectVersionTaggingAction: {},
- DeleteObjectVersionAction: {},
- DeleteObjectVersionTaggingAction: {},
- PutObjectVersionTaggingAction: {},
- GetObjectTaggingAction: {},
- PutObjectTaggingAction: {},
- DeleteObjectTaggingAction: {},
- PutBucketEncryptionAction: {},
- GetBucketEncryptionAction: {},
- PutBucketVersioningAction: {},
- GetBucketVersioningAction: {},
- GetReplicationConfigurationAction: {},
- PutReplicationConfigurationAction: {},
- ReplicateObjectAction: {},
- ReplicateDeleteAction: {},
- ReplicateTagsAction: {},
- GetObjectVersionForReplicationAction: {},
- AllActions: {},
-}
-
-// List of all supported object actions.
-var supportedObjectActions = map[Action]struct{}{
- AllActions: {},
- AbortMultipartUploadAction: {},
- DeleteObjectAction: {},
- GetObjectAction: {},
- ListMultipartUploadPartsAction: {},
- PutObjectAction: {},
- BypassGovernanceRetentionAction: {},
- PutObjectRetentionAction: {},
- GetObjectRetentionAction: {},
- PutObjectLegalHoldAction: {},
- GetObjectLegalHoldAction: {},
- GetObjectTaggingAction: {},
- PutObjectTaggingAction: {},
- DeleteObjectTaggingAction: {},
- GetObjectVersionAction: {},
- GetObjectVersionTaggingAction: {},
- DeleteObjectVersionAction: {},
- DeleteObjectVersionTaggingAction: {},
- PutObjectVersionTaggingAction: {},
- ReplicateObjectAction: {},
- ReplicateDeleteAction: {},
- ReplicateTagsAction: {},
- GetObjectVersionForReplicationAction: {},
-}
-
-// isObjectAction - returns whether action is object type or not.
-func (action Action) isObjectAction() bool {
- for supAction := range supportedObjectActions {
- if action.Match(supAction) {
- return true
- }
- }
- return false
-}
-
-// Match - matches action name with action patter.
-func (action Action) Match(a Action) bool {
- return wildcard.Match(string(action), string(a))
-}
-
-// IsValid - checks if action is valid or not.
-func (action Action) IsValid() bool {
- for supAction := range supportedActions {
- if action.Match(supAction) {
- return true
- }
- }
- return false
-}
-
-type actionConditionKeyMap map[Action]condition.KeySet
-
-func (a actionConditionKeyMap) Lookup(action Action) condition.KeySet {
- var ckeysMerged = condition.NewKeySet(condition.CommonKeys...)
- for act, ckey := range a {
- if action.Match(act) {
- ckeysMerged.Merge(ckey)
- }
- }
- return ckeysMerged
-}
-
-// iamActionConditionKeyMap - holds mapping of supported condition key for an action.
-var iamActionConditionKeyMap = actionConditionKeyMap{
- AllActions: condition.NewKeySet(condition.AllSupportedKeys...),
-
- GetObjectAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3XAmzServerSideEncryption,
- condition.S3XAmzServerSideEncryptionCustomerAlgorithm,
- condition.S3VersionID,
- }, condition.CommonKeys...)...),
-
- ListBucketAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3Prefix,
- condition.S3Delimiter,
- condition.S3MaxKeys,
- }, condition.CommonKeys...)...),
-
- ListBucketVersionsAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3Prefix,
- condition.S3Delimiter,
- condition.S3MaxKeys,
- }, condition.CommonKeys...)...),
-
- DeleteObjectAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3VersionID,
- }, condition.CommonKeys...)...),
-
- PutObjectAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3XAmzCopySource,
- condition.S3XAmzServerSideEncryption,
- condition.S3XAmzServerSideEncryptionCustomerAlgorithm,
- condition.S3XAmzMetadataDirective,
- condition.S3XAmzStorageClass,
- condition.S3VersionID,
- condition.S3ObjectLockRetainUntilDate,
- condition.S3ObjectLockMode,
- condition.S3ObjectLockLegalHold,
- }, condition.CommonKeys...)...),
-
- // https://docs.aws.amazon.com/AmazonS3/latest/dev/list_amazons3.html
- // LockLegalHold is not supported with PutObjectRetentionAction
- PutObjectRetentionAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3XAmzServerSideEncryption,
- condition.S3XAmzServerSideEncryptionCustomerAlgorithm,
- condition.S3ObjectLockRemainingRetentionDays,
- condition.S3ObjectLockRetainUntilDate,
- condition.S3ObjectLockMode,
- condition.S3VersionID,
- }, condition.CommonKeys...)...),
-
- GetObjectRetentionAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3XAmzServerSideEncryption,
- condition.S3XAmzServerSideEncryptionCustomerAlgorithm,
- condition.S3VersionID,
- }, condition.CommonKeys...)...),
-
- PutObjectLegalHoldAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3XAmzServerSideEncryption,
- condition.S3XAmzServerSideEncryptionCustomerAlgorithm,
- condition.S3ObjectLockLegalHold,
- condition.S3VersionID,
- }, condition.CommonKeys...)...),
- GetObjectLegalHoldAction: condition.NewKeySet(condition.CommonKeys...),
-
- // https://docs.aws.amazon.com/AmazonS3/latest/dev/list_amazons3.html
- BypassGovernanceRetentionAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3VersionID,
- condition.S3ObjectLockRemainingRetentionDays,
- condition.S3ObjectLockRetainUntilDate,
- condition.S3ObjectLockMode,
- condition.S3ObjectLockLegalHold,
- }, condition.CommonKeys...)...),
-
- PutObjectTaggingAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3VersionID,
- }, condition.CommonKeys...)...),
- GetObjectTaggingAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3VersionID,
- }, condition.CommonKeys...)...),
- DeleteObjectTaggingAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3VersionID,
- }, condition.CommonKeys...)...),
-
- PutObjectVersionTaggingAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3VersionID,
- }, condition.CommonKeys...)...),
- GetObjectVersionAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3VersionID,
- }, condition.CommonKeys...)...),
- GetObjectVersionTaggingAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3VersionID,
- }, condition.CommonKeys...)...),
- DeleteObjectVersionAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3VersionID,
- }, condition.CommonKeys...)...),
- DeleteObjectVersionTaggingAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3VersionID,
- }, condition.CommonKeys...)...),
- ReplicateObjectAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3VersionID,
- }, condition.CommonKeys...)...),
- ReplicateDeleteAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3VersionID,
- }, condition.CommonKeys...)...),
- ReplicateTagsAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3VersionID,
- }, condition.CommonKeys...)...),
- GetObjectVersionForReplicationAction: condition.NewKeySet(
- append([]condition.Key{
- condition.S3VersionID,
- }, condition.CommonKeys...)...),
-}
diff --git a/pkg/iam/policy/action_test.go b/pkg/iam/policy/action_test.go
deleted file mode 100644
index f1e940910..000000000
--- a/pkg/iam/policy/action_test.go
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package iampolicy
-
-import (
- "testing"
-)
-
-func TestActionIsObjectAction(t *testing.T) {
- testCases := []struct {
- action Action
- expectedResult bool
- }{
- {AbortMultipartUploadAction, true},
- {DeleteObjectAction, true},
- {GetObjectAction, true},
- {ListMultipartUploadPartsAction, true},
- {PutObjectAction, true},
- {CreateBucketAction, false},
- }
-
- for i, testCase := range testCases {
- result := testCase.action.isObjectAction()
-
- if testCase.expectedResult != result {
- t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestActionIsValid(t *testing.T) {
- testCases := []struct {
- action Action
- expectedResult bool
- }{
- {PutObjectAction, true},
- {AbortMultipartUploadAction, true},
- {Action("foo"), false},
- }
-
- for i, testCase := range testCases {
- result := testCase.action.IsValid()
-
- if testCase.expectedResult != result {
- t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
-}
diff --git a/pkg/iam/policy/actionset.go b/pkg/iam/policy/actionset.go
deleted file mode 100644
index d8f1be3c0..000000000
--- a/pkg/iam/policy/actionset.go
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package iampolicy
-
-import (
- "encoding/json"
- "fmt"
- "sort"
-
- "github.com/minio/minio-go/v7/pkg/set"
-)
-
-// ActionSet - set of actions.
-type ActionSet map[Action]struct{}
-
-// Clone clones ActionSet structure
-func (actionSet ActionSet) Clone() ActionSet {
- return NewActionSet(actionSet.ToSlice()...)
-}
-
-// Add - add action to the set.
-func (actionSet ActionSet) Add(action Action) {
- actionSet[action] = struct{}{}
-}
-
-// IsEmpty - returns if the current action set is empty
-func (actionSet ActionSet) IsEmpty() bool {
- return len(actionSet) == 0
-}
-
-// Match - matches object name with anyone of action pattern in action set.
-func (actionSet ActionSet) Match(action Action) bool {
- for r := range actionSet {
- if r.Match(action) {
- return true
- }
-
- // This is a special case where GetObjectVersion
- // means GetObject is enabled implicitly.
- switch r {
- case GetObjectVersionAction:
- if action == GetObjectAction {
- return true
- }
- }
- }
-
- return false
-}
-
-// Equals - checks whether given action set is equal to current action set or not.
-func (actionSet ActionSet) Equals(sactionSet ActionSet) bool {
- // If length of set is not equal to length of given set, the
- // set is not equal to given set.
- if len(actionSet) != len(sactionSet) {
- return false
- }
-
- // As both sets are equal in length, check each elements are equal.
- for k := range actionSet {
- if _, ok := sactionSet[k]; !ok {
- return false
- }
- }
-
- return true
-}
-
-// Intersection - returns actions available in both ActionSet.
-func (actionSet ActionSet) Intersection(sset ActionSet) ActionSet {
- nset := NewActionSet()
- for k := range actionSet {
- if _, ok := sset[k]; ok {
- nset.Add(k)
- }
- }
-
- return nset
-}
-
-// MarshalJSON - encodes ActionSet to JSON data.
-func (actionSet ActionSet) MarshalJSON() ([]byte, error) {
- if len(actionSet) == 0 {
- return nil, Errorf("empty action set")
- }
-
- return json.Marshal(actionSet.ToSlice())
-}
-
-func (actionSet ActionSet) String() string {
- actions := []string{}
- for action := range actionSet {
- actions = append(actions, string(action))
- }
- sort.Strings(actions)
-
- return fmt.Sprintf("%v", actions)
-}
-
-// ToSlice - returns slice of actions from the action set.
-func (actionSet ActionSet) ToSlice() []Action {
- actions := []Action{}
- for action := range actionSet {
- actions = append(actions, action)
- }
-
- return actions
-}
-
-// ToAdminSlice - returns slice of admin actions from the action set.
-func (actionSet ActionSet) ToAdminSlice() []AdminAction {
- actions := []AdminAction{}
- for action := range actionSet {
- actions = append(actions, AdminAction(action))
- }
-
- return actions
-}
-
-// UnmarshalJSON - decodes JSON data to ActionSet.
-func (actionSet *ActionSet) UnmarshalJSON(data []byte) error {
- var sset set.StringSet
- if err := json.Unmarshal(data, &sset); err != nil {
- return err
- }
-
- if len(sset) == 0 {
- return Errorf("empty action set")
- }
-
- *actionSet = make(ActionSet)
- for _, s := range sset.ToSlice() {
- actionSet.Add(Action(s))
- }
-
- return nil
-}
-
-// ValidateAdmin checks if all actions are valid Admin actions
-func (actionSet ActionSet) ValidateAdmin() error {
- for _, action := range actionSet.ToAdminSlice() {
- if !action.IsValid() {
- return Errorf("unsupported admin action '%v'", action)
- }
- }
- return nil
-}
-
-// Validate checks if all actions are valid
-func (actionSet ActionSet) Validate() error {
- for _, action := range actionSet.ToSlice() {
- if !action.IsValid() {
- return Errorf("unsupported action '%v'", action)
- }
- }
- return nil
-}
-
-// NewActionSet - creates new action set.
-func NewActionSet(actions ...Action) ActionSet {
- actionSet := make(ActionSet)
- for _, action := range actions {
- actionSet.Add(action)
- }
-
- return actionSet
-}
diff --git a/pkg/iam/policy/actionset_test.go b/pkg/iam/policy/actionset_test.go
deleted file mode 100644
index 57c58edf3..000000000
--- a/pkg/iam/policy/actionset_test.go
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package iampolicy
-
-import (
- "encoding/json"
- "reflect"
- "testing"
-)
-
-func TestActionSetAdd(t *testing.T) {
- testCases := []struct {
- set ActionSet
- action Action
- expectedResult ActionSet
- }{
- {NewActionSet(), PutObjectAction, NewActionSet(PutObjectAction)},
- {NewActionSet(PutObjectAction), PutObjectAction, NewActionSet(PutObjectAction)},
- }
-
- for i, testCase := range testCases {
- testCase.set.Add(testCase.action)
-
- if !reflect.DeepEqual(testCase.expectedResult, testCase.set) {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, testCase.set)
- }
- }
-}
-
-func TestActionSetMatches(t *testing.T) {
- testCases := []struct {
- set ActionSet
- action Action
- expectedResult bool
- }{
- {NewActionSet(AllActions), AbortMultipartUploadAction, true},
- {NewActionSet(PutObjectAction), PutObjectAction, true},
- {NewActionSet(PutObjectAction, GetObjectAction), PutObjectAction, true},
- {NewActionSet(PutObjectAction, GetObjectAction), AbortMultipartUploadAction, false},
- }
-
- for i, testCase := range testCases {
- result := testCase.set.Match(testCase.action)
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestActionSetIntersection(t *testing.T) {
- testCases := []struct {
- set ActionSet
- setToIntersect ActionSet
- expectedResult ActionSet
- }{
- {NewActionSet(), NewActionSet(PutObjectAction), NewActionSet()},
- {NewActionSet(PutObjectAction), NewActionSet(), NewActionSet()},
- {NewActionSet(PutObjectAction), NewActionSet(PutObjectAction, GetObjectAction), NewActionSet(PutObjectAction)},
- }
-
- for i, testCase := range testCases {
- result := testCase.set.Intersection(testCase.setToIntersect)
-
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, testCase.set)
- }
- }
-}
-
-func TestActionSetMarshalJSON(t *testing.T) {
- testCases := []struct {
- actionSet ActionSet
- expectedResult []byte
- expectErr bool
- }{
- {NewActionSet(PutObjectAction), []byte(`["s3:PutObject"]`), false},
- {NewActionSet(), nil, true},
- }
-
- for i, testCase := range testCases {
- result, err := json.Marshal(testCase.actionSet)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, string(testCase.expectedResult), string(result))
- }
- }
- }
-}
-
-func TestActionSetToSlice(t *testing.T) {
- testCases := []struct {
- actionSet ActionSet
- expectedResult []Action
- }{
- {NewActionSet(PutObjectAction), []Action{PutObjectAction}},
- {NewActionSet(), []Action{}},
- }
-
- for i, testCase := range testCases {
- result := testCase.actionSet.ToSlice()
-
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestActionSetUnmarshalJSON(t *testing.T) {
- testCases := []struct {
- data []byte
- expectedResult ActionSet
- expectUnmarshalErr bool
- expectValidateErr bool
- }{
- {[]byte(`"s3:PutObject"`), NewActionSet(PutObjectAction), false, false},
- {[]byte(`["s3:PutObject"]`), NewActionSet(PutObjectAction), false, false},
- {[]byte(`["s3:PutObject", "s3:GetObject"]`), NewActionSet(PutObjectAction, GetObjectAction), false, false},
- {[]byte(`["s3:PutObject", "s3:GetObject", "s3:PutObject"]`), NewActionSet(PutObjectAction, GetObjectAction), false, false},
- {[]byte(`[]`), NewActionSet(), true, false}, // Empty array.
- {[]byte(`"foo"`), nil, false, true}, // Invalid action.
- {[]byte(`["s3:PutObject", "foo"]`), nil, false, true}, // Invalid action.
- }
-
- for i, testCase := range testCases {
- result := make(ActionSet)
- err := json.Unmarshal(testCase.data, &result)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectUnmarshalErr {
- t.Fatalf("case %v: error during unmarshal: expected: %v, got: %v\n", i+1, testCase.expectUnmarshalErr, expectErr)
- }
-
- err = result.Validate()
- expectErr = (err != nil)
- if expectErr != testCase.expectValidateErr {
- t.Fatalf("case %v: error during validation: expected: %v, got: %v\n", i+1, testCase.expectValidateErr, expectErr)
- }
-
- if !testCase.expectUnmarshalErr && !testCase.expectValidateErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
diff --git a/pkg/iam/policy/admin-action.go b/pkg/iam/policy/admin-action.go
deleted file mode 100644
index 241b41bc1..000000000
--- a/pkg/iam/policy/admin-action.go
+++ /dev/null
@@ -1,246 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package iampolicy
-
-import (
- "github.com/minio/minio/pkg/bucket/policy/condition"
-)
-
-// AdminAction - admin policy action.
-type AdminAction string
-
-const (
- // HealAdminAction - allows heal command
- HealAdminAction = "admin:Heal"
-
- // Service Actions
-
- // StorageInfoAdminAction - allow listing server info
- StorageInfoAdminAction = "admin:StorageInfo"
- // PrometheusAdminAction - prometheus info action
- PrometheusAdminAction = "admin:Prometheus"
- // DataUsageInfoAdminAction - allow listing data usage info
- DataUsageInfoAdminAction = "admin:DataUsageInfo"
- // ForceUnlockAdminAction - allow force unlocking locks
- ForceUnlockAdminAction = "admin:ForceUnlock"
- // TopLocksAdminAction - allow listing top locks
- TopLocksAdminAction = "admin:TopLocksInfo"
- // ProfilingAdminAction - allow profiling
- ProfilingAdminAction = "admin:Profiling"
- // TraceAdminAction - allow listing server trace
- TraceAdminAction = "admin:ServerTrace"
- // ConsoleLogAdminAction - allow listing console logs on terminal
- ConsoleLogAdminAction = "admin:ConsoleLog"
- // KMSCreateKeyAdminAction - allow creating a new KMS master key
- KMSCreateKeyAdminAction = "admin:KMSCreateKey"
- // KMSKeyStatusAdminAction - allow getting KMS key status
- KMSKeyStatusAdminAction = "admin:KMSKeyStatus"
- // ServerInfoAdminAction - allow listing server info
- ServerInfoAdminAction = "admin:ServerInfo"
- // HealthInfoAdminAction - allow obtaining cluster health information
- HealthInfoAdminAction = "admin:OBDInfo"
- // BandwidthMonitorAction - allow monitoring bandwidth usage
- BandwidthMonitorAction = "admin:BandwidthMonitor"
-
- // ServerUpdateAdminAction - allow MinIO binary update
- ServerUpdateAdminAction = "admin:ServerUpdate"
- // ServiceRestartAdminAction - allow restart of MinIO service.
- ServiceRestartAdminAction = "admin:ServiceRestart"
- // ServiceStopAdminAction - allow stopping MinIO service.
- ServiceStopAdminAction = "admin:ServiceStop"
-
- // ConfigUpdateAdminAction - allow MinIO config management
- ConfigUpdateAdminAction = "admin:ConfigUpdate"
-
- // CreateUserAdminAction - allow creating MinIO user
- CreateUserAdminAction = "admin:CreateUser"
- // DeleteUserAdminAction - allow deleting MinIO user
- DeleteUserAdminAction = "admin:DeleteUser"
- // ListUsersAdminAction - allow list users permission
- ListUsersAdminAction = "admin:ListUsers"
- // EnableUserAdminAction - allow enable user permission
- EnableUserAdminAction = "admin:EnableUser"
- // DisableUserAdminAction - allow disable user permission
- DisableUserAdminAction = "admin:DisableUser"
- // GetUserAdminAction - allows GET permission on user info
- GetUserAdminAction = "admin:GetUser"
-
- // Service account Actions
-
- // CreateServiceAccountAdminAction - allow create a service account for a user
- CreateServiceAccountAdminAction = "admin:CreateServiceAccount"
- // UpdateServiceAccountAdminAction - allow updating a service account
- UpdateServiceAccountAdminAction = "admin:UpdateServiceAccount"
- // RemoveServiceAccountAdminAction - allow removing a service account
- RemoveServiceAccountAdminAction = "admin:RemoveServiceAccount"
- // ListServiceAccountsAdminAction - allow listing service accounts
- ListServiceAccountsAdminAction = "admin:ListServiceAccounts"
-
- // Group Actions
-
- // AddUserToGroupAdminAction - allow adding user to group permission
- AddUserToGroupAdminAction = "admin:AddUserToGroup"
- // RemoveUserFromGroupAdminAction - allow removing user to group permission
- RemoveUserFromGroupAdminAction = "admin:RemoveUserFromGroup"
- // GetGroupAdminAction - allow getting group info
- GetGroupAdminAction = "admin:GetGroup"
- // ListGroupsAdminAction - allow list groups permission
- ListGroupsAdminAction = "admin:ListGroups"
- // EnableGroupAdminAction - allow enable group permission
- EnableGroupAdminAction = "admin:EnableGroup"
- // DisableGroupAdminAction - allow disable group permission
- DisableGroupAdminAction = "admin:DisableGroup"
-
- // Policy Actions
-
- // CreatePolicyAdminAction - allow create policy permission
- CreatePolicyAdminAction = "admin:CreatePolicy"
- // DeletePolicyAdminAction - allow delete policy permission
- DeletePolicyAdminAction = "admin:DeletePolicy"
- // GetPolicyAdminAction - allow get policy permission
- GetPolicyAdminAction = "admin:GetPolicy"
- // AttachPolicyAdminAction - allows attaching a policy to a user/group
- AttachPolicyAdminAction = "admin:AttachUserOrGroupPolicy"
- // ListUserPoliciesAdminAction - allows listing user policies
- ListUserPoliciesAdminAction = "admin:ListUserPolicies"
-
- // Bucket quota Actions
-
- // SetBucketQuotaAdminAction - allow setting bucket quota
- SetBucketQuotaAdminAction = "admin:SetBucketQuota"
- // GetBucketQuotaAdminAction - allow getting bucket quota
- GetBucketQuotaAdminAction = "admin:GetBucketQuota"
-
- // Bucket Target admin Actions
-
- // SetBucketTargetAction - allow setting bucket target
- SetBucketTargetAction = "admin:SetBucketTarget"
- // GetBucketTargetAction - allow getting bucket targets
- GetBucketTargetAction = "admin:GetBucketTarget"
-
- // Remote Tier admin Actions
-
- // SetTierAction - allow adding/editing a remote tier
- SetTierAction = "admin:SetTier"
- // ListTierAction - allow listing remote tiers
- ListTierAction = "admin:ListTier"
-
- // AllAdminActions - provides all admin permissions
- AllAdminActions = "admin:*"
-)
-
-// List of all supported admin actions.
-var supportedAdminActions = map[AdminAction]struct{}{
- HealAdminAction: {},
- StorageInfoAdminAction: {},
- DataUsageInfoAdminAction: {},
- TopLocksAdminAction: {},
- ProfilingAdminAction: {},
- PrometheusAdminAction: {},
- TraceAdminAction: {},
- ConsoleLogAdminAction: {},
- KMSKeyStatusAdminAction: {},
- ServerInfoAdminAction: {},
- HealthInfoAdminAction: {},
- BandwidthMonitorAction: {},
- ServerUpdateAdminAction: {},
- ServiceRestartAdminAction: {},
- ServiceStopAdminAction: {},
- ConfigUpdateAdminAction: {},
- CreateUserAdminAction: {},
- DeleteUserAdminAction: {},
- ListUsersAdminAction: {},
- EnableUserAdminAction: {},
- DisableUserAdminAction: {},
- GetUserAdminAction: {},
- AddUserToGroupAdminAction: {},
- RemoveUserFromGroupAdminAction: {},
- GetGroupAdminAction: {},
- ListGroupsAdminAction: {},
- EnableGroupAdminAction: {},
- DisableGroupAdminAction: {},
- CreateServiceAccountAdminAction: {},
- UpdateServiceAccountAdminAction: {},
- RemoveServiceAccountAdminAction: {},
- ListServiceAccountsAdminAction: {},
- CreatePolicyAdminAction: {},
- DeletePolicyAdminAction: {},
- GetPolicyAdminAction: {},
- AttachPolicyAdminAction: {},
- ListUserPoliciesAdminAction: {},
- SetBucketQuotaAdminAction: {},
- GetBucketQuotaAdminAction: {},
- SetBucketTargetAction: {},
- GetBucketTargetAction: {},
- SetTierAction: {},
- ListTierAction: {},
- AllAdminActions: {},
-}
-
-// IsValid - checks if action is valid or not.
-func (action AdminAction) IsValid() bool {
- _, ok := supportedAdminActions[action]
- return ok
-}
-
-// adminActionConditionKeyMap - holds mapping of supported condition key for an action.
-var adminActionConditionKeyMap = map[Action]condition.KeySet{
- AllAdminActions: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- HealAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- StorageInfoAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- ServerInfoAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- DataUsageInfoAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- HealthInfoAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- BandwidthMonitorAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- TopLocksAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- ProfilingAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- TraceAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- ConsoleLogAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- KMSKeyStatusAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- ServerUpdateAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- ServiceRestartAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- ServiceStopAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- ConfigUpdateAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- CreateUserAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- DeleteUserAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- ListUsersAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- EnableUserAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- DisableUserAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- GetUserAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- AddUserToGroupAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- RemoveUserFromGroupAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- ListGroupsAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- EnableGroupAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- DisableGroupAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- CreateServiceAccountAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- UpdateServiceAccountAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- RemoveServiceAccountAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- ListServiceAccountsAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
-
- CreatePolicyAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- DeletePolicyAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- GetPolicyAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- AttachPolicyAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- ListUserPoliciesAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- SetBucketQuotaAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- GetBucketQuotaAdminAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- SetBucketTargetAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- GetBucketTargetAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- SetTierAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
- ListTierAction: condition.NewKeySet(condition.AllSupportedAdminKeys...),
-}
diff --git a/pkg/iam/policy/constants.go b/pkg/iam/policy/constants.go
deleted file mode 100644
index e1aa9de52..000000000
--- a/pkg/iam/policy/constants.go
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package iampolicy
-
-import (
- "github.com/minio/minio/pkg/bucket/policy"
- "github.com/minio/minio/pkg/bucket/policy/condition"
-)
-
-// Policy claim constants
-const (
- PolicyName = "policy"
- SessionPolicyName = "sessionPolicy"
-)
-
-// ReadWrite - provides full access to all buckets and all objects
-var ReadWrite = Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- {
- SID: policy.ID(""),
- Effect: policy.Allow,
- Actions: NewActionSet(AllActions),
- Resources: NewResourceSet(NewResource("*", "")),
- },
- },
-}
-
-// ReadOnly - read only.
-var ReadOnly = Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- {
- SID: policy.ID(""),
- Effect: policy.Allow,
- Actions: NewActionSet(GetBucketLocationAction, GetObjectAction),
- Resources: NewResourceSet(NewResource("*", "")),
- },
- },
-}
-
-// WriteOnly - provides write access.
-var WriteOnly = Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- {
- SID: policy.ID(""),
- Effect: policy.Allow,
- Actions: NewActionSet(PutObjectAction),
- Resources: NewResourceSet(NewResource("*", "")),
- },
- },
-}
-
-// AdminDiagnostics - provides admin diagnostics access.
-var AdminDiagnostics = Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- {
- SID: policy.ID(""),
- Effect: policy.Allow,
- Actions: NewActionSet(ProfilingAdminAction,
- TraceAdminAction, ConsoleLogAdminAction,
- ServerInfoAdminAction, TopLocksAdminAction,
- HealthInfoAdminAction, BandwidthMonitorAction,
- PrometheusAdminAction,
- ),
- Resources: NewResourceSet(NewResource("*", "")),
- },
- },
-}
-
-// Admin - provides admin all-access canned policy
-var Admin = Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- {
- SID: policy.ID(""),
- Effect: policy.Allow,
- Actions: NewActionSet(AllAdminActions),
- Resources: NewResourceSet(),
- Conditions: condition.NewFunctions(),
- },
- {
- SID: policy.ID(""),
- Effect: policy.Allow,
- Actions: NewActionSet(AllActions),
- Resources: NewResourceSet(NewResource("*", "")),
- Conditions: condition.NewFunctions(),
- },
- },
-}
diff --git a/pkg/iam/policy/error.go b/pkg/iam/policy/error.go
deleted file mode 100644
index 8aa2cf3c5..000000000
--- a/pkg/iam/policy/error.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package iampolicy
-
-import (
- "fmt"
-)
-
-// Error is the generic type for any error happening during policy
-// parsing.
-type Error struct {
- err error
-}
-
-// Errorf - formats according to a format specifier and returns
-// the string as a value that satisfies error of type policy.Error
-func Errorf(format string, a ...interface{}) error {
- return Error{err: fmt.Errorf(format, a...)}
-}
-
-// Unwrap the internal error.
-func (e Error) Unwrap() error { return e.err }
-
-// Error 'error' compatible method.
-func (e Error) Error() string {
- if e.err == nil {
- return "iam: cause "
- }
- return e.err.Error()
-}
diff --git a/pkg/iam/policy/policy.go b/pkg/iam/policy/policy.go
deleted file mode 100644
index de8b86acb..000000000
--- a/pkg/iam/policy/policy.go
+++ /dev/null
@@ -1,229 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package iampolicy
-
-import (
- "encoding/json"
- "io"
- "strings"
-
- "github.com/minio/minio-go/v7/pkg/set"
- "github.com/minio/minio/pkg/bucket/policy"
-)
-
-// DefaultVersion - default policy version as per AWS S3 specification.
-const DefaultVersion = "2012-10-17"
-
-// Args - arguments to policy to check whether it is allowed
-type Args struct {
- AccountName string `json:"account"`
- Groups []string `json:"groups"`
- Action Action `json:"action"`
- BucketName string `json:"bucket"`
- ConditionValues map[string][]string `json:"conditions"`
- IsOwner bool `json:"owner"`
- ObjectName string `json:"object"`
- Claims map[string]interface{} `json:"claims"`
- DenyOnly bool `json:"denyOnly"` // only applies deny
-}
-
-// GetPoliciesFromClaims returns the list of policies to be applied for this
-// incoming request, extracting the information from input JWT claims.
-func GetPoliciesFromClaims(claims map[string]interface{}, policyClaimName string) (set.StringSet, bool) {
- s := set.NewStringSet()
- pname, ok := claims[policyClaimName]
- if !ok {
- return s, false
- }
- pnames, ok := pname.([]interface{})
- if !ok {
- pnameStr, ok := pname.(string)
- if ok {
- for _, pname := range strings.Split(pnameStr, ",") {
- pname = strings.TrimSpace(pname)
- if pname == "" {
- // ignore any empty strings, considerate
- // towards some user errors.
- continue
- }
- s.Add(pname)
- }
- return s, true
- }
- return s, false
- }
- for _, pname := range pnames {
- pnameStr, ok := pname.(string)
- if ok {
- for _, pnameStr := range strings.Split(pnameStr, ",") {
- pnameStr = strings.TrimSpace(pnameStr)
- if pnameStr == "" {
- // ignore any empty strings, considerate
- // towards some user errors.
- continue
- }
- s.Add(pnameStr)
- }
- }
- }
- return s, true
-}
-
-// GetPolicies returns the list of policies to be applied for this
-// incoming request, extracting the information from JWT claims.
-func (a Args) GetPolicies(policyClaimName string) (set.StringSet, bool) {
- return GetPoliciesFromClaims(a.Claims, policyClaimName)
-}
-
-// Policy - iam bucket iamp.
-type Policy struct {
- ID policy.ID `json:"ID,omitempty"`
- Version string
- Statements []Statement `json:"Statement"`
-}
-
-// MatchResource matches resource with match resource patterns
-func (iamp Policy) MatchResource(resource string) bool {
- for _, statement := range iamp.Statements {
- if statement.Resources.MatchResource(resource) {
- return true
- }
- }
- return false
-}
-
-// IsAllowed - checks given policy args is allowed to continue the Rest API.
-func (iamp Policy) IsAllowed(args Args) bool {
- // Check all deny statements. If any one statement denies, return false.
- for _, statement := range iamp.Statements {
- if statement.Effect == policy.Deny {
- if !statement.IsAllowed(args) {
- return false
- }
- }
- }
-
- // Applied any 'Deny' only policies, if we have
- // reached here it means that there were no 'Deny'
- // policies - this function mainly used for
- // specific scenarios where we only want to validate
- // 'Deny' only policies.
- if args.DenyOnly {
- return true
- }
-
- // For owner, its allowed by default.
- if args.IsOwner {
- return true
- }
-
- // Check all allow statements. If any one statement allows, return true.
- for _, statement := range iamp.Statements {
- if statement.Effect == policy.Allow {
- if statement.IsAllowed(args) {
- return true
- }
- }
- }
-
- return false
-}
-
-// IsEmpty - returns whether policy is empty or not.
-func (iamp Policy) IsEmpty() bool {
- return len(iamp.Statements) == 0
-}
-
-// isValid - checks if Policy is valid or not.
-func (iamp Policy) isValid() error {
- if iamp.Version != DefaultVersion && iamp.Version != "" {
- return Errorf("invalid version '%v'", iamp.Version)
- }
-
- for _, statement := range iamp.Statements {
- if err := statement.isValid(); err != nil {
- return err
- }
- }
- return nil
-}
-
-// Merge merges two policies documents and drop
-// duplicate statements if any.
-func (iamp Policy) Merge(input Policy) Policy {
- var mergedPolicy Policy
- if iamp.Version != "" {
- mergedPolicy.Version = iamp.Version
- } else {
- mergedPolicy.Version = input.Version
- }
- for _, st := range iamp.Statements {
- mergedPolicy.Statements = append(mergedPolicy.Statements, st.Clone())
- }
- for _, st := range input.Statements {
- mergedPolicy.Statements = append(mergedPolicy.Statements, st.Clone())
- }
- mergedPolicy.dropDuplicateStatements()
- return mergedPolicy
-}
-
-func (iamp *Policy) dropDuplicateStatements() {
-redo:
- for i := range iamp.Statements {
- for j, statement := range iamp.Statements[i+1:] {
- if !iamp.Statements[i].Equals(statement) {
- continue
- }
- iamp.Statements = append(iamp.Statements[:j], iamp.Statements[j+1:]...)
- goto redo
- }
- }
-}
-
-// UnmarshalJSON - decodes JSON data to Iamp.
-func (iamp *Policy) UnmarshalJSON(data []byte) error {
- // subtype to avoid recursive call to UnmarshalJSON()
- type subPolicy Policy
- var sp subPolicy
- if err := json.Unmarshal(data, &sp); err != nil {
- return err
- }
-
- p := Policy(sp)
- p.dropDuplicateStatements()
- *iamp = p
- return nil
-}
-
-// Validate - validates all statements are for given bucket or not.
-func (iamp Policy) Validate() error {
- return iamp.isValid()
-}
-
-// ParseConfig - parses data in given reader to Iamp.
-func ParseConfig(reader io.Reader) (*Policy, error) {
- var iamp Policy
-
- decoder := json.NewDecoder(reader)
- decoder.DisallowUnknownFields()
- if err := decoder.Decode(&iamp); err != nil {
- return nil, Errorf("%w", err)
- }
-
- return &iamp, iamp.Validate()
-}
diff --git a/pkg/iam/policy/policy_test.go b/pkg/iam/policy/policy_test.go
deleted file mode 100644
index 3aa9e220d..000000000
--- a/pkg/iam/policy/policy_test.go
+++ /dev/null
@@ -1,1173 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package iampolicy
-
-import (
- "encoding/json"
- "net"
- "reflect"
- "strings"
- "testing"
- "time"
-
- "github.com/minio/minio-go/v7/pkg/set"
- "github.com/minio/minio/pkg/bucket/policy"
- "github.com/minio/minio/pkg/bucket/policy/condition"
-)
-
-func TestGetPoliciesFromClaims(t *testing.T) {
- attributesArray := `{
- "exp": 1594690452,
- "iat": 1594689552,
- "auth_time": 1594689552,
- "jti": "18ed05c9-2c69-45d5-a33f-8c94aca99ad5",
- "iss": "http://localhost:8080/auth/realms/minio",
- "aud": "account",
- "sub": "7e5e2f30-1c97-4616-8623-2eae14dee9b1",
- "typ": "ID",
- "azp": "account",
- "nonce": "66ZoLzwJbjdkiedI",
- "session_state": "3df7b526-5310-4038-9f35-50ecd295a31d",
- "acr": "1",
- "upn": "harsha",
- "address": {},
- "email_verified": false,
- "groups": [
- "offline_access"
- ],
- "preferred_username": "harsha",
- "policy": [
- "readwrite",
- "readwrite,readonly",
- " readonly",
- ""
- ]}`
- var m = make(map[string]interface{})
- if err := json.Unmarshal([]byte(attributesArray), &m); err != nil {
- t.Fatal(err)
- }
- var expectedSet = set.CreateStringSet("readwrite", "readonly")
- gotSet, ok := GetPoliciesFromClaims(m, "policy")
- if !ok {
- t.Fatal("no policy claim was found")
- }
- if gotSet.IsEmpty() {
- t.Fatal("no policies were found in policy claim")
- }
- if !gotSet.Equals(expectedSet) {
- t.Fatalf("Expected %v got %v", expectedSet, gotSet)
- }
-}
-
-func TestPolicyIsAllowed(t *testing.T) {
- case1Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- policy.Allow,
- NewActionSet(GetBucketLocationAction, PutObjectAction),
- NewResourceSet(NewResource("*", "")),
- condition.NewFunctions(),
- )},
- }
-
- case2Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- policy.Allow,
- NewActionSet(GetObjectAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- )},
- }
-
- _, IPNet, err := net.ParseCIDR("192.168.1.0/24")
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- func1, err := condition.NewIPAddressFunc(
- condition.AWSSourceIP,
- IPNet,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- policy.Allow,
- NewActionSet(GetObjectAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(func1),
- )},
- }
-
- case4Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- policy.Deny,
- NewActionSet(GetObjectAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(func1),
- )},
- }
-
- anonGetBucketLocationArgs := Args{
- AccountName: "Q3AM3UQ867SPQQA43P2F",
- Action: GetBucketLocationAction,
- BucketName: "mybucket",
- ConditionValues: map[string][]string{},
- }
-
- anonPutObjectActionArgs := Args{
- AccountName: "Q3AM3UQ867SPQQA43P2F",
- Action: PutObjectAction,
- BucketName: "mybucket",
- ConditionValues: map[string][]string{
- "x-amz-copy-source": {"mybucket/myobject"},
- "SourceIp": {"192.168.1.10"},
- },
- ObjectName: "myobject",
- }
-
- anonGetObjectActionArgs := Args{
- AccountName: "Q3AM3UQ867SPQQA43P2F",
- Action: GetObjectAction,
- BucketName: "mybucket",
- ConditionValues: map[string][]string{},
- ObjectName: "myobject",
- }
-
- getBucketLocationArgs := Args{
- AccountName: "Q3AM3UQ867SPQQA43P2F",
- Action: GetBucketLocationAction,
- BucketName: "mybucket",
- ConditionValues: map[string][]string{},
- }
-
- putObjectActionArgs := Args{
- AccountName: "Q3AM3UQ867SPQQA43P2F",
- Action: PutObjectAction,
- BucketName: "mybucket",
- ConditionValues: map[string][]string{
- "x-amz-copy-source": {"mybucket/myobject"},
- "SourceIp": {"192.168.1.10"},
- },
- ObjectName: "myobject",
- }
-
- getObjectActionArgs := Args{
- AccountName: "Q3AM3UQ867SPQQA43P2F",
- Action: GetObjectAction,
- BucketName: "mybucket",
- ConditionValues: map[string][]string{},
- ObjectName: "myobject",
- }
-
- testCases := []struct {
- policy Policy
- args Args
- expectedResult bool
- }{
- {case1Policy, anonGetBucketLocationArgs, true},
- {case1Policy, anonPutObjectActionArgs, true},
- {case1Policy, anonGetObjectActionArgs, false},
- {case1Policy, getBucketLocationArgs, true},
- {case1Policy, putObjectActionArgs, true},
- {case1Policy, getObjectActionArgs, false},
-
- {case2Policy, anonGetBucketLocationArgs, false},
- {case2Policy, anonPutObjectActionArgs, true},
- {case2Policy, anonGetObjectActionArgs, true},
- {case2Policy, getBucketLocationArgs, false},
- {case2Policy, putObjectActionArgs, true},
- {case2Policy, getObjectActionArgs, true},
-
- {case3Policy, anonGetBucketLocationArgs, false},
- {case3Policy, anonPutObjectActionArgs, true},
- {case3Policy, anonGetObjectActionArgs, false},
- {case3Policy, getBucketLocationArgs, false},
- {case3Policy, putObjectActionArgs, true},
- {case3Policy, getObjectActionArgs, false},
-
- {case4Policy, anonGetBucketLocationArgs, false},
- {case4Policy, anonPutObjectActionArgs, false},
- {case4Policy, anonGetObjectActionArgs, false},
- {case4Policy, getBucketLocationArgs, false},
- {case4Policy, putObjectActionArgs, false},
- {case4Policy, getObjectActionArgs, false},
- }
-
- for i, testCase := range testCases {
- result := testCase.policy.IsAllowed(testCase.args)
-
- if result != testCase.expectedResult {
- t.Errorf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestPolicyIsEmpty(t *testing.T) {
- case1Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- policy.Allow,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- case2Policy := Policy{
- ID: "MyPolicyForMyBucket",
- Version: DefaultVersion,
- }
-
- testCases := []struct {
- policy Policy
- expectedResult bool
- }{
- {case1Policy, false},
- {case2Policy, true},
- }
-
- for i, testCase := range testCases {
- result := testCase.policy.IsEmpty()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestPolicyIsValid(t *testing.T) {
- case1Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- policy.Allow,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- case2Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- policy.Allow,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- NewStatement(
- policy.Deny,
- NewActionSet(GetObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- case3Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- policy.Allow,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- NewStatement(
- policy.Deny,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/yourobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- func1, err := condition.NewNullFunc(
- condition.S3XAmzCopySource,
- true,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- func2, err := condition.NewNullFunc(
- condition.S3XAmzServerSideEncryption,
- false,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case4Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- policy.Allow,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(func1),
- ),
- NewStatement(
- policy.Deny,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(func2),
- ),
- },
- }
-
- case5Policy := Policy{
- Version: "17-10-2012",
- Statements: []Statement{
- NewStatement(
- policy.Allow,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- case6Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- policy.Allow,
- NewActionSet(GetObjectAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "myobject*")),
- condition.NewFunctions(func1, func2),
- ),
- },
- }
-
- case7Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- policy.Allow,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- NewStatement(
- policy.Deny,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- case8Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- policy.Allow,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- NewStatement(
- policy.Allow,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- testCases := []struct {
- policy Policy
- expectErr bool
- }{
- {case1Policy, false},
- // allowed duplicate principal.
- {case2Policy, false},
- // allowed duplicate principal and action.
- {case3Policy, false},
- // allowed duplicate principal, action and resource.
- {case4Policy, false},
- // Invalid version error.
- {case5Policy, true},
- // Invalid statement error.
- {case6Policy, true},
- // Duplicate statement different Effects.
- {case7Policy, false},
- // Duplicate statement same Effects, duplicate effect will be removed.
- {case8Policy, false},
- }
-
- for i, testCase := range testCases {
- err := testCase.policy.isValid()
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
- }
-}
-
-// Parse config with location constraints
-func TestPolicyParseConfig(t *testing.T) {
- policy1LocationConstraint := `{
- "Version":"2012-10-17",
- "Statement":[
- {
- "Sid":"statement1",
- "Effect":"Allow",
- "Action": "s3:CreateBucket",
- "Resource": "arn:aws:s3:::*",
- "Condition": {
- "StringLike": {
- "s3:LocationConstraint": "us-east-1"
- }
- }
- },
- {
- "Sid":"statement2",
- "Effect":"Deny",
- "Action": "s3:CreateBucket",
- "Resource": "arn:aws:s3:::*",
- "Condition": {
- "StringNotLike": {
- "s3:LocationConstraint": "us-east-1"
- }
- }
- }
- ]
-}`
- policy2Condition := `{
- "Version": "2012-10-17",
- "Statement": [
- {
- "Sid": "statement1",
- "Effect": "Allow",
- "Action": "s3:GetObjectVersion",
- "Resource": "arn:aws:s3:::test/HappyFace.jpg"
- },
- {
- "Sid": "statement2",
- "Effect": "Deny",
- "Action": "s3:GetObjectVersion",
- "Resource": "arn:aws:s3:::test/HappyFace.jpg",
- "Condition": {
- "StringNotEquals": {
- "s3:versionid": "AaaHbAQitwiL_h47_44lRO2DDfLlBO5e"
- }
- }
- }
- ]
-}`
-
- policy3ConditionActionRegex := `{
- "Version": "2012-10-17",
- "Statement": [
- {
- "Sid": "statement2",
- "Effect": "Allow",
- "Action": "s3:Get*",
- "Resource": "arn:aws:s3:::test/HappyFace.jpg",
- "Condition": {
- "StringEquals": {
- "s3:versionid": "AaaHbAQitwiL_h47_44lRO2DDfLlBO5e"
- }
- }
- }
- ]
-}`
-
- policy4ConditionAction := `{
- "Version": "2012-10-17",
- "Statement": [
- {
- "Sid": "statement2",
- "Effect": "Allow",
- "Action": "s3:GetObject",
- "Resource": "arn:aws:s3:::test/HappyFace.jpg",
- "Condition": {
- "StringEquals": {
- "s3:versionid": "AaaHbAQitwiL_h47_44lRO2DDfLlBO5e"
- }
- }
- }
- ]
-}`
-
- policy5ConditionCurrenTime := `{
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Action": [
- "s3:Get*",
- "s3:Put*"
- ],
- "Resource": [
- "arn:aws:s3:::test/*"
- ],
- "Condition": {
- "DateGreaterThan": {
- "aws:CurrentTime": [
- "2017-02-28T00:00:00Z"
- ]
- }
- }
- }
- ]
-}`
-
- policy5ConditionCurrenTimeLesser := `{
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Action": [
- "s3:Get*",
- "s3:Put*"
- ],
- "Resource": [
- "arn:aws:s3:::test/*"
- ],
- "Condition": {
- "DateLessThan": {
- "aws:CurrentTime": [
- "2017-02-28T00:00:00Z"
- ]
- }
- }
- }
- ]
-}`
-
- tests := []struct {
- p string
- args Args
- allowed bool
- }{
- {
- p: policy1LocationConstraint,
- allowed: true,
- args: Args{
- AccountName: "allowed",
- Action: CreateBucketAction,
- BucketName: "test",
- ConditionValues: map[string][]string{"LocationConstraint": {"us-east-1"}},
- },
- },
- {
- p: policy1LocationConstraint,
- allowed: false,
- args: Args{
- AccountName: "disallowed",
- Action: CreateBucketAction,
- BucketName: "test",
- ConditionValues: map[string][]string{"LocationConstraint": {"us-east-2"}},
- },
- },
- {
- p: policy2Condition,
- allowed: true,
- args: Args{
- AccountName: "allowed",
- Action: GetObjectAction,
- BucketName: "test",
- ObjectName: "HappyFace.jpg",
- ConditionValues: map[string][]string{"versionid": {"AaaHbAQitwiL_h47_44lRO2DDfLlBO5e"}},
- },
- },
- {
- p: policy2Condition,
- allowed: false,
- args: Args{
- AccountName: "disallowed",
- Action: GetObjectAction,
- BucketName: "test",
- ObjectName: "HappyFace.jpg",
- ConditionValues: map[string][]string{"versionid": {"AaaHbAQitwiL_h47_44lRO2DDfLlBO5f"}},
- },
- },
- {
- p: policy3ConditionActionRegex,
- allowed: true,
- args: Args{
- AccountName: "allowed",
- Action: GetObjectAction,
- BucketName: "test",
- ObjectName: "HappyFace.jpg",
- ConditionValues: map[string][]string{"versionid": {"AaaHbAQitwiL_h47_44lRO2DDfLlBO5e"}},
- },
- },
- {
- p: policy3ConditionActionRegex,
- allowed: false,
- args: Args{
- AccountName: "disallowed",
- Action: GetObjectAction,
- BucketName: "test",
- ObjectName: "HappyFace.jpg",
- ConditionValues: map[string][]string{"versionid": {"AaaHbAQitwiL_h47_44lRO2DDfLlBO5f"}},
- },
- },
- {
- p: policy4ConditionAction,
- allowed: true,
- args: Args{
- AccountName: "allowed",
- Action: GetObjectAction,
- BucketName: "test",
- ObjectName: "HappyFace.jpg",
- ConditionValues: map[string][]string{"versionid": {"AaaHbAQitwiL_h47_44lRO2DDfLlBO5e"}},
- },
- },
- {
- p: policy5ConditionCurrenTime,
- allowed: true,
- args: Args{
- AccountName: "allowed",
- Action: GetObjectAction,
- BucketName: "test",
- ObjectName: "HappyFace.jpg",
- ConditionValues: map[string][]string{
- "CurrentTime": {time.Now().Format(time.RFC3339)},
- },
- },
- },
- {
- p: policy5ConditionCurrenTimeLesser,
- allowed: false,
- args: Args{
- AccountName: "disallowed",
- Action: GetObjectAction,
- BucketName: "test",
- ObjectName: "HappyFace.jpg",
- ConditionValues: map[string][]string{
- "CurrentTime": {time.Now().Format(time.RFC3339)},
- },
- },
- },
- }
- for _, test := range tests {
- test := test
- t.Run(test.args.AccountName, func(t *testing.T) {
- ip, err := ParseConfig(strings.NewReader(test.p))
- if err != nil {
- t.Error(err)
- }
- if got := ip.IsAllowed(test.args); got != test.allowed {
- t.Errorf("Expected %t, got %t", test.allowed, got)
- }
- })
- }
-}
-
-func TestPolicyUnmarshalJSONAndValidate(t *testing.T) {
- case1Data := []byte(`{
- "ID": "MyPolicyForMyBucket1",
- "Version": "2012-10-17",
- "Statement": [
- {
- "Sid": "SomeId1",
- "Effect": "Allow",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
- }
- ]
-}`)
- case1Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- policy.Allow,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
- case1Policy.Statements[0].SID = "SomeId1"
-
- case2Data := []byte(`{
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
- },
- {
- "Effect": "Deny",
- "Action": "s3:GetObject",
- "Resource": "arn:aws:s3:::mybucket/yourobject*",
- "Condition": {
- "IpAddress": {
- "aws:SourceIp": "192.168.1.0/24"
- }
- }
- }
- ]
-}`)
- _, IPNet1, err := net.ParseCIDR("192.168.1.0/24")
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- func1, err := condition.NewIPAddressFunc(
- condition.AWSSourceIP,
- IPNet1,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case2Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- policy.Allow,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- NewStatement(
- policy.Deny,
- NewActionSet(GetObjectAction),
- NewResourceSet(NewResource("mybucket", "/yourobject*")),
- condition.NewFunctions(func1),
- ),
- },
- }
-
- case3Data := []byte(`{
- "ID": "MyPolicyForMyBucket1",
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Action": "s3:GetObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
- },
- {
- "Effect": "Allow",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
- }
- ]
-}`)
- case3Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- policy.Allow,
- NewActionSet(GetObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- NewStatement(
- policy.Allow,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- case4Data := []byte(`{
- "ID": "MyPolicyForMyBucket1",
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
- },
- {
- "Effect": "Allow",
- "Action": "s3:GetObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
- }
- ]
-}`)
- case4Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- policy.Allow,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- NewStatement(
- policy.Allow,
- NewActionSet(GetObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- case5Data := []byte(`{
- "ID": "MyPolicyForMyBucket1",
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
- },
- {
- "Effect": "Allow",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/yourobject*"
- }
- ]
-}`)
- case5Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- policy.Allow,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- ),
- NewStatement(
- policy.Allow,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/yourobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- case6Data := []byte(`{
- "ID": "MyPolicyForMyBucket1",
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*",
- "Condition": {
- "IpAddress": {
- "aws:SourceIp": "192.168.1.0/24"
- }
- }
- },
- {
- "Effect": "Allow",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*",
- "Condition": {
- "IpAddress": {
- "aws:SourceIp": "192.168.2.0/24"
- }
- }
- }
- ]
-}`)
- _, IPNet2, err := net.ParseCIDR("192.168.2.0/24")
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- func2, err := condition.NewIPAddressFunc(
- condition.AWSSourceIP,
- IPNet2,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case6Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- policy.Allow,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(func1),
- ),
- NewStatement(
- policy.Allow,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(func2),
- ),
- },
- }
-
- case7Data := []byte(`{
- "ID": "MyPolicyForMyBucket1",
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Action": "s3:GetBucketLocation",
- "Resource": "arn:aws:s3:::mybucket"
- }
- ]
-}`)
-
- case7Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- policy.Allow,
- NewActionSet(GetBucketLocationAction),
- NewResourceSet(NewResource("mybucket", "")),
- condition.NewFunctions(),
- ),
- },
- }
-
- case8Data := []byte(`{
- "ID": "MyPolicyForMyBucket1",
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Action": "s3:GetBucketLocation",
- "Resource": "arn:aws:s3:::*"
- }
- ]
-}`)
-
- case8Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- policy.Allow,
- NewActionSet(GetBucketLocationAction),
- NewResourceSet(NewResource("*", "")),
- condition.NewFunctions(),
- ),
- },
- }
-
- case9Data := []byte(`{
- "ID": "MyPolicyForMyBucket1",
- "Version": "17-10-2012",
- "Statement": [
- {
- "Effect": "Allow",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
- }
- ]
-}`)
-
- case10Data := []byte(`{
- "ID": "MyPolicyForMyBucket1",
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
- },
- {
- "Effect": "Allow",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
- }
- ]
-}`)
- case10Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- policy.Allow,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- case11Data := []byte(`{
- "ID": "MyPolicyForMyBucket1",
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
- },
- {
- "Effect": "Deny",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
- }
- ]
-}`)
-
- case11Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- policy.Allow,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "myobject*")),
- condition.NewFunctions(),
- ),
- NewStatement(
- policy.Deny,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- testCases := []struct {
- data []byte
- expectedResult Policy
- expectUnmarshalErr bool
- expectValidationErr bool
- }{
- {case1Data, case1Policy, false, false},
- {case2Data, case2Policy, false, false},
- {case3Data, case3Policy, false, false},
- {case4Data, case4Policy, false, false},
- {case5Data, case5Policy, false, false},
- {case6Data, case6Policy, false, false},
- {case7Data, case7Policy, false, false},
- {case8Data, case8Policy, false, false},
- // Invalid version error.
- {case9Data, Policy{}, false, true},
- // Duplicate statement success, duplicate statement is removed.
- {case10Data, case10Policy, false, false},
- // Duplicate statement success (Effect differs).
- {case11Data, case11Policy, false, false},
- }
-
- for i, testCase := range testCases {
- var result Policy
- err := json.Unmarshal(testCase.data, &result)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectUnmarshalErr {
- t.Errorf("case %v: error during unmarshal: expected: %v, got: %v", i+1, testCase.expectUnmarshalErr, expectErr)
- }
-
- err = result.Validate()
- expectErr = (err != nil)
-
- if expectErr != testCase.expectValidationErr {
- t.Errorf("case %v: error during validation: expected: %v, got: %v", i+1, testCase.expectValidationErr, expectErr)
- }
-
- if !testCase.expectUnmarshalErr && !testCase.expectValidationErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Errorf("case %v: result: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
-
-func TestPolicyValidate(t *testing.T) {
- case1Policy := Policy{
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- policy.Allow,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("", "")),
- condition.NewFunctions(),
- ),
- },
- }
-
- func1, err := condition.NewNullFunc(
- condition.S3XAmzCopySource,
- true,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- func2, err := condition.NewNullFunc(
- condition.S3XAmzServerSideEncryption,
- false,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- case2Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- policy.Allow,
- NewActionSet(GetObjectAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "myobject*")),
- condition.NewFunctions(func1, func2),
- ),
- },
- }
-
- case3Policy := Policy{
- ID: "MyPolicyForMyBucket1",
- Version: DefaultVersion,
- Statements: []Statement{
- NewStatement(
- policy.Allow,
- NewActionSet(GetObjectAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "myobject*")),
- condition.NewFunctions(),
- ),
- },
- }
-
- testCases := []struct {
- policy Policy
- expectErr bool
- }{
- {case1Policy, true},
- {case2Policy, true},
- {case3Policy, false},
- }
-
- for i, testCase := range testCases {
- err := testCase.policy.Validate()
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
- }
-}
diff --git a/pkg/iam/policy/resource.go b/pkg/iam/policy/resource.go
deleted file mode 100644
index 8d8ea337f..000000000
--- a/pkg/iam/policy/resource.go
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package iampolicy
-
-import (
- "encoding/json"
- "path"
- "strings"
-
- "github.com/minio/minio/pkg/bucket/policy/condition"
- "github.com/minio/pkg/wildcard"
-)
-
-// ResourceARNPrefix - resource ARN prefix as per AWS S3 specification.
-const ResourceARNPrefix = "arn:aws:s3:::"
-
-// Resource - resource in policy statement.
-type Resource struct {
- BucketName string
- Pattern string
-}
-
-func (r Resource) isBucketPattern() bool {
- return !strings.Contains(r.Pattern, "/") || r.Pattern == "*"
-}
-
-func (r Resource) isObjectPattern() bool {
- return strings.Contains(r.Pattern, "/") || strings.Contains(r.BucketName, "*") || r.Pattern == "*/*"
-}
-
-// IsValid - checks whether Resource is valid or not.
-func (r Resource) IsValid() bool {
- return r.Pattern != ""
-}
-
-// MatchResource matches object name with resource pattern only.
-func (r Resource) MatchResource(resource string) bool {
- return r.Match(resource, nil)
-}
-
-// Match - matches object name with resource pattern, including specific conditionals.
-func (r Resource) Match(resource string, conditionValues map[string][]string) bool {
- pattern := r.Pattern
- for _, key := range condition.CommonKeys {
- // Empty values are not supported for policy variables.
- if rvalues, ok := conditionValues[key.Name()]; ok && rvalues[0] != "" {
- pattern = strings.Replace(pattern, key.VarName(), rvalues[0], -1)
- }
- }
- if cp := path.Clean(resource); cp != "." && cp == pattern {
- return true
- }
- return wildcard.Match(pattern, resource)
-}
-
-// MarshalJSON - encodes Resource to JSON data.
-func (r Resource) MarshalJSON() ([]byte, error) {
- if !r.IsValid() {
- return nil, Errorf("invalid resource %v", r)
- }
-
- return json.Marshal(r.String())
-}
-
-func (r Resource) String() string {
- return ResourceARNPrefix + r.Pattern
-}
-
-// UnmarshalJSON - decodes JSON data to Resource.
-func (r *Resource) UnmarshalJSON(data []byte) error {
- var s string
- if err := json.Unmarshal(data, &s); err != nil {
- return err
- }
-
- parsedResource, err := parseResource(s)
- if err != nil {
- return err
- }
-
- *r = parsedResource
-
- return nil
-}
-
-// Validate - validates Resource is for given bucket or not.
-func (r Resource) Validate() error {
- if !r.IsValid() {
- return Errorf("invalid resource")
- }
- return nil
-}
-
-// parseResource - parses string to Resource.
-func parseResource(s string) (Resource, error) {
- if !strings.HasPrefix(s, ResourceARNPrefix) {
- return Resource{}, Errorf("invalid resource '%v'", s)
- }
-
- pattern := strings.TrimPrefix(s, ResourceARNPrefix)
- tokens := strings.SplitN(pattern, "/", 2)
- bucketName := tokens[0]
- if bucketName == "" {
- return Resource{}, Errorf("invalid resource format '%v'", s)
- }
-
- return Resource{
- BucketName: bucketName,
- Pattern: pattern,
- }, nil
-}
-
-// NewResource - creates new resource.
-func NewResource(bucketName, keyName string) Resource {
- pattern := bucketName
- if keyName != "" {
- if !strings.HasPrefix(keyName, "/") {
- pattern += "/"
- }
-
- pattern += keyName
- }
-
- return Resource{
- BucketName: bucketName,
- Pattern: pattern,
- }
-}
diff --git a/pkg/iam/policy/resource_test.go b/pkg/iam/policy/resource_test.go
deleted file mode 100644
index a383084e8..000000000
--- a/pkg/iam/policy/resource_test.go
+++ /dev/null
@@ -1,224 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package iampolicy
-
-import (
- "encoding/json"
- "fmt"
- "reflect"
- "testing"
-)
-
-func TestResourceIsBucketPattern(t *testing.T) {
- testCases := []struct {
- resource Resource
- expectedResult bool
- }{
- {NewResource("*", ""), true},
- {NewResource("mybucket", ""), true},
- {NewResource("mybucket*", ""), true},
- {NewResource("mybucket?0", ""), true},
- {NewResource("", "*"), false},
- {NewResource("*", "*"), false},
- {NewResource("mybucket", "*"), false},
- {NewResource("mybucket*", "/myobject"), false},
- {NewResource("mybucket?0", "/2010/photos/*"), false},
- }
-
- for i, testCase := range testCases {
- result := testCase.resource.isBucketPattern()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestResourceIsObjectPattern(t *testing.T) {
- testCases := []struct {
- resource Resource
- expectedResult bool
- }{
- {NewResource("*", ""), true},
- {NewResource("mybucket*", ""), true},
- {NewResource("", "*"), true},
- {NewResource("*", "*"), true},
- {NewResource("mybucket", "*"), true},
- {NewResource("mybucket*", "/myobject"), true},
- {NewResource("mybucket?0", "/2010/photos/*"), true},
- {NewResource("mybucket", ""), false},
- {NewResource("mybucket?0", ""), false},
- }
-
- for i, testCase := range testCases {
- result := testCase.resource.isObjectPattern()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestResourceIsValid(t *testing.T) {
- testCases := []struct {
- resource Resource
- expectedResult bool
- }{
- {NewResource("*", ""), true},
- {NewResource("mybucket*", ""), true},
- {NewResource("*", "*"), true},
- {NewResource("mybucket", "*"), true},
- {NewResource("mybucket*", "/myobject"), true},
- {NewResource("mybucket?0", "/2010/photos/*"), true},
- {NewResource("mybucket", ""), true},
- {NewResource("mybucket?0", ""), true},
- {NewResource("", "*"), true},
- {NewResource("", ""), false},
- }
-
- for i, testCase := range testCases {
- result := testCase.resource.IsValid()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestResourceMatch(t *testing.T) {
- testCases := []struct {
- resource Resource
- objectName string
- expectedResult bool
- }{
- {NewResource("*", ""), "mybucket", true},
- {NewResource("*", ""), "mybucket/myobject", true},
- {NewResource("mybucket*", ""), "mybucket", true},
- {NewResource("mybucket*", ""), "mybucket/myobject", true},
- {NewResource("", "*"), "/myobject", true},
- {NewResource("*", "*"), "mybucket/myobject", true},
- {NewResource("mybucket", "*"), "mybucket/myobject", true},
- {NewResource("mybucket*", "/myobject"), "mybucket/myobject", true},
- {NewResource("mybucket*", "/myobject"), "mybucket100/myobject", true},
- {NewResource("mybucket?0", "/2010/photos/*"), "mybucket20/2010/photos/1.jpg", true},
- {NewResource("mybucket", ""), "mybucket", true},
- {NewResource("mybucket?0", ""), "mybucket30", true},
- {NewResource("", "*"), "mybucket/myobject", false},
- {NewResource("*", "*"), "mybucket", false},
- {NewResource("mybucket", "*"), "mybucket10/myobject", false},
- {NewResource("mybucket?0", "/2010/photos/*"), "mybucket0/2010/photos/1.jpg", false},
- {NewResource("mybucket", ""), "mybucket/myobject", false},
- }
-
- for i, testCase := range testCases {
- testCase := testCase
- t.Run(fmt.Sprintf("Test%d", i+1), func(t *testing.T) {
- result := testCase.resource.Match(testCase.objectName, nil)
- if result != testCase.expectedResult {
- t.Errorf("case %v: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- })
- }
-}
-
-func TestResourceMarshalJSON(t *testing.T) {
- testCases := []struct {
- resource Resource
- expectedResult []byte
- expectErr bool
- }{
- {NewResource("*", ""), []byte(`"arn:aws:s3:::*"`), false},
- {NewResource("mybucket*", ""), []byte(`"arn:aws:s3:::mybucket*"`), false},
- {NewResource("mybucket", ""), []byte(`"arn:aws:s3:::mybucket"`), false},
- {NewResource("*", "*"), []byte(`"arn:aws:s3:::*/*"`), false},
- {NewResource("", "*"), []byte(`"arn:aws:s3:::/*"`), false},
- {NewResource("mybucket", "*"), []byte(`"arn:aws:s3:::mybucket/*"`), false},
- {NewResource("mybucket*", "myobject"), []byte(`"arn:aws:s3:::mybucket*/myobject"`), false},
- {NewResource("mybucket?0", "/2010/photos/*"), []byte(`"arn:aws:s3:::mybucket?0/2010/photos/*"`), false},
- {Resource{}, nil, true},
- }
-
- for i, testCase := range testCases {
- result, err := json.Marshal(testCase.resource)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v", i+1, string(testCase.expectedResult), string(result))
- }
- }
- }
-}
-
-func TestResourceUnmarshalJSON(t *testing.T) {
- testCases := []struct {
- data []byte
- expectedResult Resource
- expectErr bool
- }{
- {[]byte(`"arn:aws:s3:::*"`), NewResource("*", ""), false},
- {[]byte(`"arn:aws:s3:::mybucket*"`), NewResource("mybucket*", ""), false},
- {[]byte(`"arn:aws:s3:::mybucket"`), NewResource("mybucket", ""), false},
- {[]byte(`"arn:aws:s3:::*/*"`), NewResource("*", "*"), false},
- {[]byte(`"arn:aws:s3:::mybucket/*"`), NewResource("mybucket", "*"), false},
- {[]byte(`"arn:aws:s3:::mybucket*/myobject"`), NewResource("mybucket*", "myobject"), false},
- {[]byte(`"arn:aws:s3:::mybucket?0/2010/photos/*"`), NewResource("mybucket?0", "/2010/photos/*"), false},
- {[]byte(`"mybucket/myobject*"`), Resource{}, true},
- {[]byte(`"arn:aws:s3:::/*"`), Resource{}, true},
- }
-
- for i, testCase := range testCases {
- var result Resource
- err := json.Unmarshal(testCase.data, &result)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
-
-func TestResourceValidate(t *testing.T) {
- testCases := []struct {
- resource Resource
- expectErr bool
- }{
- {NewResource("mybucket", "/myobject*"), false},
- {NewResource("", "/myobject*"), false},
- {NewResource("", ""), true},
- }
-
- for i, testCase := range testCases {
- err := testCase.resource.Validate()
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
- }
-}
diff --git a/pkg/iam/policy/resourceset.go b/pkg/iam/policy/resourceset.go
deleted file mode 100644
index 3b16568ca..000000000
--- a/pkg/iam/policy/resourceset.go
+++ /dev/null
@@ -1,191 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package iampolicy
-
-import (
- "encoding/json"
- "fmt"
- "sort"
-
- "github.com/minio/minio-go/v7/pkg/set"
-)
-
-// ResourceSet - set of resources in policy statement.
-type ResourceSet map[Resource]struct{}
-
-// bucketResourceExists - checks if at least one bucket resource exists in the set.
-func (resourceSet ResourceSet) bucketResourceExists() bool {
- for resource := range resourceSet {
- if resource.isBucketPattern() {
- return true
- }
- }
-
- return false
-}
-
-// objectResourceExists - checks if at least one object resource exists in the set.
-func (resourceSet ResourceSet) objectResourceExists() bool {
- for resource := range resourceSet {
- if resource.isObjectPattern() {
- return true
- }
- }
-
- return false
-}
-
-// Add - adds resource to resource set.
-func (resourceSet ResourceSet) Add(resource Resource) {
- resourceSet[resource] = struct{}{}
-}
-
-// Equals - checks whether given resource set is equal to current resource set or not.
-func (resourceSet ResourceSet) Equals(sresourceSet ResourceSet) bool {
- // If length of set is not equal to length of given set, the
- // set is not equal to given set.
- if len(resourceSet) != len(sresourceSet) {
- return false
- }
-
- // As both sets are equal in length, check each elements are equal.
- for k := range resourceSet {
- if _, ok := sresourceSet[k]; !ok {
- return false
- }
- }
-
- return true
-}
-
-// Intersection - returns resources available in both ResourceSet.
-func (resourceSet ResourceSet) Intersection(sset ResourceSet) ResourceSet {
- nset := NewResourceSet()
- for k := range resourceSet {
- if _, ok := sset[k]; ok {
- nset.Add(k)
- }
- }
-
- return nset
-}
-
-// MarshalJSON - encodes ResourceSet to JSON data.
-func (resourceSet ResourceSet) MarshalJSON() ([]byte, error) {
- if len(resourceSet) == 0 {
- return nil, Errorf("empty resource set")
- }
-
- resources := []Resource{}
- for resource := range resourceSet {
- resources = append(resources, resource)
- }
-
- return json.Marshal(resources)
-}
-
-// MatchResource matches object name with resource patterns only.
-func (resourceSet ResourceSet) MatchResource(resource string) bool {
- for r := range resourceSet {
- if r.MatchResource(resource) {
- return true
- }
- }
- return false
-}
-
-// Match - matches object name with anyone of resource pattern in resource set.
-func (resourceSet ResourceSet) Match(resource string, conditionValues map[string][]string) bool {
- for r := range resourceSet {
- if r.Match(resource, conditionValues) {
- return true
- }
- }
-
- return false
-}
-
-func (resourceSet ResourceSet) String() string {
- resources := []string{}
- for resource := range resourceSet {
- resources = append(resources, resource.String())
- }
- sort.Strings(resources)
-
- return fmt.Sprintf("%v", resources)
-}
-
-// UnmarshalJSON - decodes JSON data to ResourceSet.
-func (resourceSet *ResourceSet) UnmarshalJSON(data []byte) error {
- var sset set.StringSet
- if err := json.Unmarshal(data, &sset); err != nil {
- return err
- }
-
- *resourceSet = make(ResourceSet)
- for _, s := range sset.ToSlice() {
- resource, err := parseResource(s)
- if err != nil {
- return err
- }
-
- if _, found := (*resourceSet)[resource]; found {
- return Errorf("duplicate resource '%v' found", s)
- }
-
- resourceSet.Add(resource)
- }
-
- return nil
-}
-
-// Validate - validates ResourceSet.
-func (resourceSet ResourceSet) Validate() error {
- for resource := range resourceSet {
- if err := resource.Validate(); err != nil {
- return err
- }
- }
-
- return nil
-}
-
-// ToSlice - returns slice of resources from the resource set.
-func (resourceSet ResourceSet) ToSlice() []Resource {
- resources := []Resource{}
- for resource := range resourceSet {
- resources = append(resources, resource)
- }
-
- return resources
-}
-
-// Clone clones ResourceSet structure
-func (resourceSet ResourceSet) Clone() ResourceSet {
- return NewResourceSet(resourceSet.ToSlice()...)
-}
-
-// NewResourceSet - creates new resource set.
-func NewResourceSet(resources ...Resource) ResourceSet {
- resourceSet := make(ResourceSet)
- for _, resource := range resources {
- resourceSet.Add(resource)
- }
-
- return resourceSet
-}
diff --git a/pkg/iam/policy/resourceset_test.go b/pkg/iam/policy/resourceset_test.go
deleted file mode 100644
index 5cf4f6692..000000000
--- a/pkg/iam/policy/resourceset_test.go
+++ /dev/null
@@ -1,243 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package iampolicy
-
-import (
- "encoding/json"
- "fmt"
- "reflect"
- "testing"
-)
-
-func TestResourceSetBucketResourceExists(t *testing.T) {
- testCases := []struct {
- resourceSet ResourceSet
- expectedResult bool
- }{
- {NewResourceSet(NewResource("*", "")), true},
- {NewResourceSet(NewResource("mybucket", "")), true},
- {NewResourceSet(NewResource("mybucket*", "")), true},
- {NewResourceSet(NewResource("mybucket?0", "")), true},
- {NewResourceSet(NewResource("mybucket", "/2010/photos/*"), NewResource("mybucket", "")), true},
- {NewResourceSet(NewResource("", "*")), false},
- {NewResourceSet(NewResource("*", "*")), false},
- {NewResourceSet(NewResource("mybucket", "*")), false},
- {NewResourceSet(NewResource("mybucket*", "/myobject")), false},
- {NewResourceSet(NewResource("mybucket?0", "/2010/photos/*")), false},
- }
-
- for i, testCase := range testCases {
- result := testCase.resourceSet.bucketResourceExists()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestResourceSetObjectResourceExists(t *testing.T) {
- testCases := []struct {
- resourceSet ResourceSet
- expectedResult bool
- }{
- {NewResourceSet(NewResource("*", "")), true},
- {NewResourceSet(NewResource("mybucket*", "")), true},
- {NewResourceSet(NewResource("", "*")), true},
- {NewResourceSet(NewResource("*", "*")), true},
- {NewResourceSet(NewResource("mybucket", "*")), true},
- {NewResourceSet(NewResource("mybucket*", "/myobject")), true},
- {NewResourceSet(NewResource("mybucket?0", "/2010/photos/*")), true},
- {NewResourceSet(NewResource("mybucket", ""), NewResource("mybucket", "/2910/photos/*")), true},
- {NewResourceSet(NewResource("mybucket", "")), false},
- {NewResourceSet(NewResource("mybucket?0", "")), false},
- }
-
- for i, testCase := range testCases {
- result := testCase.resourceSet.objectResourceExists()
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestResourceSetAdd(t *testing.T) {
- testCases := []struct {
- resourceSet ResourceSet
- resource Resource
- expectedResult ResourceSet
- }{
- {NewResourceSet(), NewResource("mybucket", "/myobject*"),
- NewResourceSet(NewResource("mybucket", "/myobject*"))},
- {NewResourceSet(NewResource("mybucket", "/myobject*")),
- NewResource("mybucket", "/yourobject*"),
- NewResourceSet(NewResource("mybucket", "/myobject*"),
- NewResource("mybucket", "/yourobject*"))},
- {NewResourceSet(NewResource("mybucket", "/myobject*")),
- NewResource("mybucket", "/myobject*"),
- NewResourceSet(NewResource("mybucket", "/myobject*"))},
- }
-
- for i, testCase := range testCases {
- testCase.resourceSet.Add(testCase.resource)
-
- if !reflect.DeepEqual(testCase.resourceSet, testCase.expectedResult) {
- t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectedResult, testCase.resourceSet)
- }
- }
-}
-
-func TestResourceSetIntersection(t *testing.T) {
- testCases := []struct {
- set ResourceSet
- setToIntersect ResourceSet
- expectedResult ResourceSet
- }{
- {NewResourceSet(), NewResourceSet(NewResource("mybucket", "/myobject*")), NewResourceSet()},
- {NewResourceSet(NewResource("mybucket", "/myobject*")), NewResourceSet(), NewResourceSet()},
- {NewResourceSet(NewResource("mybucket", "/myobject*")),
- NewResourceSet(NewResource("mybucket", "/myobject*"), NewResource("mybucket", "/yourobject*")),
- NewResourceSet(NewResource("mybucket", "/myobject*"))},
- }
-
- for i, testCase := range testCases {
- result := testCase.set.Intersection(testCase.setToIntersect)
-
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, testCase.set)
- }
- }
-}
-
-func TestResourceSetMarshalJSON(t *testing.T) {
- testCases := []struct {
- resoruceSet ResourceSet
- expectedResult []byte
- expectErr bool
- }{
- {NewResourceSet(NewResource("mybucket", "/myobject*")),
- []byte(`["arn:aws:s3:::mybucket/myobject*"]`), false},
- {NewResourceSet(NewResource("mybucket", "/photos/myobject*")),
- []byte(`["arn:aws:s3:::mybucket/photos/myobject*"]`), false},
- {NewResourceSet(), nil, true},
- }
-
- for i, testCase := range testCases {
- result, err := json.Marshal(testCase.resoruceSet)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v", i+1, string(testCase.expectedResult), string(result))
- }
- }
- }
-}
-
-func TestResourceSetMatch(t *testing.T) {
- testCases := []struct {
- resourceSet ResourceSet
- resource string
- expectedResult bool
- }{
- {NewResourceSet(NewResource("*", "")), "mybucket", true},
- {NewResourceSet(NewResource("*", "")), "mybucket/myobject", true},
- {NewResourceSet(NewResource("mybucket*", "")), "mybucket", true},
- {NewResourceSet(NewResource("mybucket*", "")), "mybucket/myobject", true},
- {NewResourceSet(NewResource("", "*")), "/myobject", true},
- {NewResourceSet(NewResource("*", "*")), "mybucket/myobject", true},
- {NewResourceSet(NewResource("mybucket", "*")), "mybucket/myobject", true},
- {NewResourceSet(NewResource("mybucket*", "/myobject")), "mybucket/myobject", true},
- {NewResourceSet(NewResource("mybucket*", "/myobject")), "mybucket100/myobject", true},
- {NewResourceSet(NewResource("mybucket?0", "/2010/photos/*")), "mybucket20/2010/photos/1.jpg", true},
- {NewResourceSet(NewResource("mybucket", "")), "mybucket", true},
- {NewResourceSet(NewResource("mybucket?0", "")), "mybucket30", true},
- {NewResourceSet(NewResource("mybucket?0", "/2010/photos/*"),
- NewResource("mybucket", "/2010/photos/*")), "mybucket/2010/photos/1.jpg", true},
- {NewResourceSet(NewResource("", "*")), "mybucket/myobject", false},
- {NewResourceSet(NewResource("*", "*")), "mybucket", false},
- {NewResourceSet(NewResource("mybucket", "*")), "mybucket10/myobject", false},
- {NewResourceSet(NewResource("mybucket", "")), "mybucket/myobject", false},
- {NewResourceSet(), "mybucket/myobject", false},
- }
-
- for i, testCase := range testCases {
- testCase := testCase
- t.Run(fmt.Sprintf("Test%d", i+1), func(t *testing.T) {
- result := testCase.resourceSet.Match(testCase.resource, nil)
- if result != testCase.expectedResult {
- t.Errorf("case %v: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- })
- }
-}
-
-func TestResourceSetUnmarshalJSON(t *testing.T) {
- testCases := []struct {
- data []byte
- expectedResult ResourceSet
- expectErr bool
- }{
- {[]byte(`"arn:aws:s3:::mybucket/myobject*"`),
- NewResourceSet(NewResource("mybucket", "/myobject*")), false},
- {[]byte(`"arn:aws:s3:::mybucket/photos/myobject*"`),
- NewResourceSet(NewResource("mybucket", "/photos/myobject*")), false},
- {[]byte(`"arn:aws:s3:::mybucket"`), NewResourceSet(NewResource("mybucket", "")), false},
- {[]byte(`"mybucket/myobject*"`), nil, true},
- }
-
- for i, testCase := range testCases {
- var result ResourceSet
- err := json.Unmarshal(testCase.data, &result)
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
-
- if !testCase.expectErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
-
-func TestResourceSetValidate(t *testing.T) {
- testCases := []struct {
- resourceSet ResourceSet
- expectErr bool
- }{
- {NewResourceSet(NewResource("mybucket", "/myobject*")), false},
- {NewResourceSet(NewResource("", "/myobject*")), false},
- {NewResourceSet(NewResource("", "")), true},
- }
-
- for i, testCase := range testCases {
- err := testCase.resourceSet.Validate()
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
- }
-}
diff --git a/pkg/iam/policy/statement.go b/pkg/iam/policy/statement.go
deleted file mode 100644
index 455e63878..000000000
--- a/pkg/iam/policy/statement.go
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package iampolicy
-
-import (
- "strings"
-
- "github.com/minio/minio/pkg/bucket/policy"
- "github.com/minio/minio/pkg/bucket/policy/condition"
-)
-
-// Statement - iam policy statement.
-type Statement struct {
- SID policy.ID `json:"Sid,omitempty"`
- Effect policy.Effect `json:"Effect"`
- Actions ActionSet `json:"Action"`
- Resources ResourceSet `json:"Resource,omitempty"`
- Conditions condition.Functions `json:"Condition,omitempty"`
-}
-
-// IsAllowed - checks given policy args is allowed to continue the Rest API.
-func (statement Statement) IsAllowed(args Args) bool {
- check := func() bool {
- if !statement.Actions.Match(args.Action) {
- return false
- }
-
- resource := args.BucketName
- if args.ObjectName != "" {
- if !strings.HasPrefix(args.ObjectName, "/") {
- resource += "/"
- }
-
- resource += args.ObjectName
- } else {
- resource += "/"
- }
-
- // For admin statements, resource match can be ignored.
- if !statement.Resources.Match(resource, args.ConditionValues) && !statement.isAdmin() {
- return false
- }
-
- return statement.Conditions.Evaluate(args.ConditionValues)
- }
-
- return statement.Effect.IsAllowed(check())
-}
-func (statement Statement) isAdmin() bool {
- for action := range statement.Actions {
- if AdminAction(action).IsValid() {
- return true
- }
- }
- return false
-}
-
-// isValid - checks whether statement is valid or not.
-func (statement Statement) isValid() error {
- if !statement.Effect.IsValid() {
- return Errorf("invalid Effect %v", statement.Effect)
- }
-
- if len(statement.Actions) == 0 {
- return Errorf("Action must not be empty")
- }
-
- if statement.isAdmin() {
- if err := statement.Actions.ValidateAdmin(); err != nil {
- return err
- }
- for action := range statement.Actions {
- keys := statement.Conditions.Keys()
- keyDiff := keys.Difference(adminActionConditionKeyMap[action])
- if !keyDiff.IsEmpty() {
- return Errorf("unsupported condition keys '%v' used for action '%v'", keyDiff, action)
- }
- }
- return nil
- }
-
- if !statement.SID.IsValid() {
- return Errorf("invalid SID %v", statement.SID)
- }
-
- if len(statement.Resources) == 0 {
- return Errorf("Resource must not be empty")
- }
-
- if err := statement.Resources.Validate(); err != nil {
- return err
- }
-
- if err := statement.Actions.Validate(); err != nil {
- return err
- }
-
- for action := range statement.Actions {
- if !statement.Resources.objectResourceExists() && !statement.Resources.bucketResourceExists() {
- return Errorf("unsupported Resource found %v for action %v", statement.Resources, action)
- }
-
- keys := statement.Conditions.Keys()
- keyDiff := keys.Difference(iamActionConditionKeyMap.Lookup(action))
- if !keyDiff.IsEmpty() {
- return Errorf("unsupported condition keys '%v' used for action '%v'", keyDiff, action)
- }
- }
-
- return nil
-}
-
-// Validate - validates Statement is for given bucket or not.
-func (statement Statement) Validate() error {
- return statement.isValid()
-}
-
-// Equals checks if two statements are equal
-func (statement Statement) Equals(st Statement) bool {
- if statement.Effect != st.Effect {
- return false
- }
- if !statement.Actions.Equals(st.Actions) {
- return false
- }
- if !statement.Resources.Equals(st.Resources) {
- return false
- }
- if !statement.Conditions.Equals(st.Conditions) {
- return false
- }
- return true
-}
-
-// Clone clones Statement structure
-func (statement Statement) Clone() Statement {
- return NewStatement(statement.Effect, statement.Actions.Clone(),
- statement.Resources.Clone(), statement.Conditions.Clone())
-}
-
-// NewStatement - creates new statement.
-func NewStatement(effect policy.Effect, actionSet ActionSet, resourceSet ResourceSet, conditions condition.Functions) Statement {
- return Statement{
- Effect: effect,
- Actions: actionSet,
- Resources: resourceSet,
- Conditions: conditions,
- }
-}
diff --git a/pkg/iam/policy/statement_test.go b/pkg/iam/policy/statement_test.go
deleted file mode 100644
index 629d99afe..000000000
--- a/pkg/iam/policy/statement_test.go
+++ /dev/null
@@ -1,467 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package iampolicy
-
-import (
- "encoding/json"
- "net"
- "reflect"
- "testing"
-
- "github.com/minio/minio/pkg/bucket/policy"
- "github.com/minio/minio/pkg/bucket/policy/condition"
-)
-
-func TestStatementIsAllowed(t *testing.T) {
- case1Statement := NewStatement(
- policy.Allow,
- NewActionSet(GetBucketLocationAction, PutObjectAction),
- NewResourceSet(NewResource("*", "")),
- condition.NewFunctions(),
- )
-
- case2Statement := NewStatement(
- policy.Allow,
- NewActionSet(GetObjectAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- )
-
- _, IPNet1, err := net.ParseCIDR("192.168.1.0/24")
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- func1, err := condition.NewIPAddressFunc(
- condition.AWSSourceIP,
- IPNet1,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- case3Statement := NewStatement(
- policy.Allow,
- NewActionSet(GetObjectAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(func1),
- )
-
- case4Statement := NewStatement(
- policy.Deny,
- NewActionSet(GetObjectAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(func1),
- )
-
- anonGetBucketLocationArgs := Args{
- AccountName: "Q3AM3UQ867SPQQA43P2F",
- Action: GetBucketLocationAction,
- BucketName: "mybucket",
- ConditionValues: map[string][]string{},
- }
-
- anonPutObjectActionArgs := Args{
- AccountName: "Q3AM3UQ867SPQQA43P2F",
- Action: PutObjectAction,
- BucketName: "mybucket",
- ConditionValues: map[string][]string{
- "x-amz-copy-source": {"mybucket/myobject"},
- "SourceIp": {"192.168.1.10"},
- },
- ObjectName: "myobject",
- }
-
- anonGetObjectActionArgs := Args{
- AccountName: "Q3AM3UQ867SPQQA43P2F",
- Action: GetObjectAction,
- BucketName: "mybucket",
- ConditionValues: map[string][]string{},
- ObjectName: "myobject",
- }
-
- getBucketLocationArgs := Args{
- AccountName: "Q3AM3UQ867SPQQA43P2F",
- Action: GetBucketLocationAction,
- BucketName: "mybucket",
- ConditionValues: map[string][]string{},
- }
-
- putObjectActionArgs := Args{
- AccountName: "Q3AM3UQ867SPQQA43P2F",
- Action: PutObjectAction,
- BucketName: "mybucket",
- ConditionValues: map[string][]string{
- "x-amz-copy-source": {"mybucket/myobject"},
- "SourceIp": {"192.168.1.10"},
- },
- ObjectName: "myobject",
- }
-
- getObjectActionArgs := Args{
- AccountName: "Q3AM3UQ867SPQQA43P2F",
- Action: GetObjectAction,
- BucketName: "mybucket",
- ConditionValues: map[string][]string{},
- ObjectName: "myobject",
- }
-
- testCases := []struct {
- statement Statement
- args Args
- expectedResult bool
- }{
- {case1Statement, anonGetBucketLocationArgs, true},
- {case1Statement, anonPutObjectActionArgs, true},
- {case1Statement, anonGetObjectActionArgs, false},
- {case1Statement, getBucketLocationArgs, true},
- {case1Statement, putObjectActionArgs, true},
- {case1Statement, getObjectActionArgs, false},
-
- {case2Statement, anonGetBucketLocationArgs, false},
- {case2Statement, anonPutObjectActionArgs, true},
- {case2Statement, anonGetObjectActionArgs, true},
- {case2Statement, getBucketLocationArgs, false},
- {case2Statement, putObjectActionArgs, true},
- {case2Statement, getObjectActionArgs, true},
-
- {case3Statement, anonGetBucketLocationArgs, false},
- {case3Statement, anonPutObjectActionArgs, true},
- {case3Statement, anonGetObjectActionArgs, false},
- {case3Statement, getBucketLocationArgs, false},
- {case3Statement, putObjectActionArgs, true},
- {case3Statement, getObjectActionArgs, false},
-
- {case4Statement, anonGetBucketLocationArgs, true},
- {case4Statement, anonPutObjectActionArgs, false},
- {case4Statement, anonGetObjectActionArgs, true},
- {case4Statement, getBucketLocationArgs, true},
- {case4Statement, putObjectActionArgs, false},
- {case4Statement, getObjectActionArgs, true},
- }
-
- for i, testCase := range testCases {
- result := testCase.statement.IsAllowed(testCase.args)
-
- if result != testCase.expectedResult {
- t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
- }
- }
-}
-
-func TestStatementIsValid(t *testing.T) {
- _, IPNet1, err := net.ParseCIDR("192.168.1.0/24")
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- func1, err := condition.NewIPAddressFunc(
- condition.AWSSourceIP,
- IPNet1,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- func2, err := condition.NewStringEqualsFunc(
- condition.S3XAmzCopySource,
- "mybucket/myobject",
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- func3, err := condition.NewStringEqualsFunc(
- condition.AWSUserAgent,
- "NSPlayer",
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
-
- testCases := []struct {
- statement Statement
- expectErr bool
- }{
- // Invalid effect error.
- {NewStatement(
- policy.Effect("foo"),
- NewActionSet(GetBucketLocationAction, PutObjectAction),
- NewResourceSet(NewResource("*", "")),
- condition.NewFunctions(),
- ), true},
- // Empty actions error.
- {NewStatement(
- policy.Allow,
- NewActionSet(),
- NewResourceSet(NewResource("*", "")),
- condition.NewFunctions(),
- ), true},
- // Empty resources error.
- {NewStatement(
- policy.Allow,
- NewActionSet(GetBucketLocationAction, PutObjectAction),
- NewResourceSet(),
- condition.NewFunctions(),
- ), true},
- // Unsupported conditions for GetObject
- {NewStatement(
- policy.Allow,
- NewActionSet(GetObjectAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "myobject*")),
- condition.NewFunctions(func1, func2),
- ), true},
- {NewStatement(
- policy.Allow,
- NewActionSet(GetBucketLocationAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "myobject*")),
- condition.NewFunctions(),
- ), false},
- {NewStatement(
- policy.Allow,
- NewActionSet(GetBucketLocationAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "")),
- condition.NewFunctions(),
- ), false},
- {NewStatement(
- policy.Deny,
- NewActionSet(GetObjectAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "myobject*")),
- condition.NewFunctions(func1),
- ), false},
- {NewStatement(
- policy.Allow,
- NewActionSet(CreateUserAdminAction, DeleteUserAdminAction),
- nil,
- condition.NewFunctions(func2, func3),
- ), true},
- {NewStatement(
- policy.Allow,
- NewActionSet(CreateUserAdminAction, DeleteUserAdminAction),
- nil,
- condition.NewFunctions(),
- ), false},
- }
-
- for i, testCase := range testCases {
- err := testCase.statement.isValid()
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
- }
-}
-
-func TestStatementUnmarshalJSONAndValidate(t *testing.T) {
- case1Data := []byte(`{
- "Sid": "SomeId1",
- "Effect": "Allow",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
-}`)
- case1Statement := NewStatement(
- policy.Allow,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- )
- case1Statement.SID = "SomeId1"
-
- case2Data := []byte(`{
- "Effect": "Allow",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*",
- "Condition": {
- "Null": {
- "s3:x-amz-copy-source": true
- }
- }
-}`)
- func1, err := condition.NewNullFunc(
- condition.S3XAmzCopySource,
- true,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- case2Statement := NewStatement(
- policy.Allow,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(func1),
- )
-
- case3Data := []byte(`{
- "Effect": "Deny",
- "Action": [
- "s3:PutObject",
- "s3:GetObject"
- ],
- "Resource": "arn:aws:s3:::mybucket/myobject*",
- "Condition": {
- "Null": {
- "s3:x-amz-server-side-encryption": "false"
- }
- }
-}`)
- func2, err := condition.NewNullFunc(
- condition.S3XAmzServerSideEncryption,
- false,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- case3Statement := NewStatement(
- policy.Deny,
- NewActionSet(PutObjectAction, GetObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(func2),
- )
-
- case4Data := []byte(`{
- "Effect": "Allow",
- "Action": "s3:PutObjec,
- "Resource": "arn:aws:s3:::mybucket/myobject*"
-}`)
-
- case5Data := []byte(`{
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
-}`)
-
- case7Data := []byte(`{
- "Effect": "Allow",
- "Resource": "arn:aws:s3:::mybucket/myobject*"
-}`)
-
- case8Data := []byte(`{
- "Effect": "Allow",
- "Action": "s3:PutObject"
-}`)
-
- case9Data := []byte(`{
- "Effect": "Allow",
- "Action": "s3:PutObject",
- "Resource": "arn:aws:s3:::mybucket/myobject*",
- "Condition": {
- }
-}`)
-
- case10Data := []byte(`{
- "Effect": "Deny",
- "Action": [
- "s3:PutObject",
- "s3:GetObject"
- ],
- "Resource": "arn:aws:s3:::mybucket/myobject*",
- "Condition": {
- "StringEquals": {
- "s3:x-amz-copy-source": "yourbucket/myobject*"
- }
- }
-}`)
-
- testCases := []struct {
- data []byte
- expectedResult Statement
- expectUnmarshalErr bool
- expectValidationErr bool
- }{
- {case1Data, case1Statement, false, false},
- {case2Data, case2Statement, false, false},
- {case3Data, case3Statement, false, false},
- // JSON unmarshaling error.
- {case4Data, Statement{}, true, true},
- // Invalid effect error.
- {case5Data, Statement{}, false, true},
- // Empty action error.
- {case7Data, Statement{}, false, true},
- // Empty resource error.
- {case8Data, Statement{}, false, true},
- // Empty condition error.
- {case9Data, Statement{}, true, false},
- // Unsupported condition key error.
- {case10Data, Statement{}, false, true},
- }
-
- for i, testCase := range testCases {
- var result Statement
- expectErr := (json.Unmarshal(testCase.data, &result) != nil)
-
- if expectErr != testCase.expectUnmarshalErr {
- t.Fatalf("case %v: error during unmarshal: expected: %v, got: %v", i+1, testCase.expectUnmarshalErr, expectErr)
- }
-
- expectErr = (result.Validate() != nil)
- if expectErr != testCase.expectValidationErr {
- t.Fatalf("case %v: error during validation: expected: %v, got: %v", i+1, testCase.expectValidationErr, expectErr)
- }
-
- if !testCase.expectUnmarshalErr && !testCase.expectValidationErr {
- if !reflect.DeepEqual(result, testCase.expectedResult) {
- t.Fatalf("case %v: result: expected: %v, got: %v", i+1, testCase.expectedResult, result)
- }
- }
- }
-}
-
-func TestStatementValidate(t *testing.T) {
- case1Statement := NewStatement(
- policy.Allow,
- NewActionSet(PutObjectAction),
- NewResourceSet(NewResource("mybucket", "/myobject*")),
- condition.NewFunctions(),
- )
-
- func1, err := condition.NewNullFunc(
- condition.S3XAmzCopySource,
- true,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- func2, err := condition.NewNullFunc(
- condition.S3XAmzServerSideEncryption,
- false,
- )
- if err != nil {
- t.Fatalf("unexpected error. %v\n", err)
- }
- case2Statement := NewStatement(
- policy.Allow,
- NewActionSet(GetObjectAction, PutObjectAction),
- NewResourceSet(NewResource("mybucket", "myobject*")),
- condition.NewFunctions(func1, func2),
- )
-
- testCases := []struct {
- statement Statement
- expectErr bool
- }{
- {case1Statement, false},
- {case2Statement, true},
- }
-
- for i, testCase := range testCases {
- err := testCase.statement.Validate()
- expectErr := (err != nil)
-
- if expectErr != testCase.expectErr {
- t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
- }
- }
-}