mirror of
https://github.com/versity/versitygw.git
synced 2026-09-24 17:04:16 +00:00
With the posix backend running --chuid/--chgid against the standalone IAM service, CreateBucket failed for every bucket name and left a half-created directory behind. Bucket ownership is fixed to the gateway's root account there, and that account was constructed from the root credentials alone, so its UserID/GroupID stayed at zero and the gateway tried to chown each new bucket to uid/gid 0 - something a process that is not root can never do. Root-account object writes failed the same way, because the identity the S3 request path uses for root also comes from the root credentials and never from the IAM backend. On top of that, the failed chown returned before the acl xattr was written, so the leftover directory made every later request for that name fail with "get bucket acl: no such key" until it was removed by hand. The standalone IAM client now reports the root account with UserID, GroupID and ProjectID taken from --iam-standalone-default-uid, -gid and -project-id, returning a copy so the stored root account keeps the credentials it is compared against. ResolveDerivedKey copies that same identity onto root when the IAM backend fixes bucket ownership to the root access key, which keeps root's own writes consistent with the buckets root owns. CreateBucket now removes the bucket directory, its sidecar attributes and its versioning directory on any failure after the mkdir, so a failed create leaves nothing behind and the name stays retryable. A chown EPERM reports the target uid/gid, the flags that asked for it and the process euid/egid instead of a bare "operation not permitted", and the posix backend warns at startup when chuid/chgid are set on an unprivileged gateway. The built-in IAM backends do not fix bucket ownership, so root and every other account reach the storage backend exactly as before.
61 lines
2.4 KiB
Go
61 lines
2.4 KiB
Go
// Copyright 2026 Versity Software
|
|
// This file is licensed under the Apache License, Version 2.0
|
|
// (the "License"); you may not use this file except in compliance
|
|
// with the License. You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package auth
|
|
|
|
// FixedBucketOwner is implemented by IAM backends that give every bucket the
|
|
// same owner instead of the account that created it — currently only the
|
|
// standalone IAM service client, which has no per-user ownership to express:
|
|
// every account is a plain RoleUser, they cannot be enumerated, and access is
|
|
// decided by IAM policy rather than by ACL.
|
|
//
|
|
// Backends that do not implement it keep per-creator ownership as before.
|
|
type FixedBucketOwner interface {
|
|
BucketOwner() Account
|
|
}
|
|
|
|
// ResolveFixedBucketOwner reports the account that owns every bucket when iam
|
|
// fixes ownership, and false when ownership follows the creator instead.
|
|
func ResolveFixedBucketOwner(iam IAMService) (Account, bool) {
|
|
fbo, ok := iam.(FixedBucketOwner)
|
|
if !ok {
|
|
return Account{}, false
|
|
}
|
|
|
|
return fbo.BucketOwner(), true
|
|
}
|
|
|
|
// rootIdentity returns the account a storage backend should see for a request
|
|
// signed with the gateway's root credentials. The S3 request path knows root
|
|
// only by its access key and secret, so root would otherwise reach the
|
|
// backend with the zero uid/gid — which the posix backend's --chuid/--chgid
|
|
// then tries to chown to, an operation an unprivileged gateway can never
|
|
// perform.
|
|
//
|
|
// An IAM backend that fixes bucket ownership to root also defines the POSIX
|
|
// identity root owns those buckets with, so take it from there: root's own
|
|
// object writes then land with the same ownership as the buckets root owns.
|
|
// Backends that do not fix ownership resolve a real per-account uid/gid for
|
|
// every other account and keep root exactly as it was.
|
|
func rootIdentity(iam IAMService, root Account) Account {
|
|
owner, fixed := ResolveFixedBucketOwner(iam)
|
|
if !fixed || owner.Access != root.Access {
|
|
return root
|
|
}
|
|
|
|
root.UserID = owner.UserID
|
|
root.GroupID = owner.GroupID
|
|
root.ProjectID = owner.ProjectID
|
|
return root
|
|
}
|