mirror of
https://github.com/versity/versitygw.git
synced 2026-10-01 12:16:12 +00:00
fix: normalize object keys during bucket policy evaluation
Object key validation allowed internal parent-directory segments such as `public/../private.txt`. Bucket policy and auth checks evaluated the raw key, so a policy allowing bucket/public/* could match the request while posix backend later resolved the key with `filepath.Join` and accessed `bucket/private.txt`. Add backend-specific object key normalization to close that mismatch. The Backend interface now exposes `NormalizeObjectKey` so authorization can evaluate resources using the same key shape a backend will use for storage access. Backends that do not collapse object paths, including Azure and the S3 proxy, inherit `BackendUnsupported.NormalizeObjectKey`. That implementation returns the input key unchanged, avoiding unnecessary normalization and keeping policy evaluation unpolluted for object stores where ../ is part of the key name. posix/scoutfs normalize keys with filepath.Join so policy resources and request keys are compared after internal dot segments are collapsed. Bucket policy evaluation now normalizes both the incoming object key and object resource patterns from the policy before matching. Object lock governance bypass policy checks use the same backend normalizer as well, so retention and legal hold authorization cannot diverge from backend path resolution.
This commit is contained in:
@@ -30,6 +30,7 @@ import (
|
||||
type Backend interface {
|
||||
fmt.Stringer
|
||||
Shutdown()
|
||||
NormalizeObjectKey(bucket, object string) string
|
||||
|
||||
// bucket operations
|
||||
ListBuckets(context.Context, s3response.ListBucketsInput) (s3response.ListAllMyBucketsResult, error)
|
||||
@@ -111,6 +112,9 @@ func (BackendUnsupported) Shutdown() {}
|
||||
func (BackendUnsupported) String() string {
|
||||
return "Unsupported"
|
||||
}
|
||||
func (BackendUnsupported) NormalizeObjectKey(_, object string) string {
|
||||
return object
|
||||
}
|
||||
func (BackendUnsupported) ListBuckets(context.Context, s3response.ListBucketsInput) (s3response.ListAllMyBucketsResult, error) {
|
||||
return s3response.ListAllMyBucketsResult{}, s3err.GetAPIError(s3err.ErrNotImplemented)
|
||||
}
|
||||
|
||||
@@ -6598,6 +6598,19 @@ func (p *Posix) ListBucketsAndOwners(ctx context.Context) (buckets []s3response.
|
||||
return buckets, nil
|
||||
}
|
||||
|
||||
func (p *Posix) NormalizeObjectKey(bucket, object string) string {
|
||||
fullPath := filepath.Join(bucket, object)
|
||||
key, err := filepath.Rel(filepath.Clean(bucket), fullPath)
|
||||
if err != nil {
|
||||
return fullPath
|
||||
}
|
||||
if key == "." {
|
||||
return ""
|
||||
}
|
||||
|
||||
return key
|
||||
}
|
||||
|
||||
func (p *Posix) storeChecksums(f *os.File, bucket, object string, chs s3response.Checksum) error {
|
||||
checksums, err := json.Marshal(chs)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user