Files
versitygw/auth/iam_single_test.go
niksis02 c99f9ba757 fix: return InvalidAccessKeyId for unknown access keys in single, Vault and IPA IAM
Fixes #2445

The S3 auth middlewares (header, presigned and POST) return 403 `InvalidAccessKeyId` only when the IAM lookup returns exactly `auth.ErrNoSuchUser`, since they compare with `==`. Three IAM backends returned a different error for an unknown access key, and the client received that error unchanged.

The root-only `IAMServiceSingle` returned the admin API's `ErrAdminUserNotFound`, so clients got 404 `XAdminUserNotFound`, which tools such as pgBackRest and rclone read as missing data rather than bad credentials. It now returns `ErrNoSuchUser`. The `ErrAdminUserNotFound` check in `resolveAccountsByLookup` is removed because no backend returns that error anymore.

In the Vault backend, `KvV2Read` of a missing key fails with a 404, which was passed through and rendered as 500 `InternalError`. The same error broke the admin `create-bucket`, `change-bucket-owner` and `update-user` commands for unknown users, which returned 500 instead of `XAdminUserNotFound`. `GetUserAccount` now maps a 404 to `ErrNoSuchUser` on both the initial read and the retry after re-authentication, the same way `ListUserAccounts` already handles 404.

FreeIPA reports a missing object as `NotFound` (code `4001`), both from `user_show` for an unknown user and from `vault_retrieve_internal` for a user who has no S3 vault. Both cases rendered as 500. `rpcInternal` now returns `errRpcNotFound`, which wraps `errRpc`, for code `4001`, and `GetUserAccount` maps it to `ErrNoSuchUser` in both places. A user without the vault has no S3 secret, so it is treated as a nonexistent account, and the PKCS#1 v1.5 to OAEP retry is skipped in that case.
2026-09-29 11:59:02 +04:00

53 lines
1.8 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
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/versity/versitygw/internal/sigv4auth"
)
func TestIAMServiceSingleGetUserAccount(t *testing.T) {
root := Account{Access: "root", Secret: "rootsecret", Role: RoleAdmin}
iam := NewIAMServiceSingle(root)
acc, err := iam.GetUserAccount("root")
assert.NoError(t, err)
assert.Equal(t, root, acc)
_, err = iam.GetUserAccount("NOSUCHKEYID0000000")
assert.Equal(t, ErrNoSuchUser, err)
}
// The S3 auth middlewares render InvalidAccessKeyId only when
// ResolveDerivedKey returns exactly ErrNoSuchUser.
func TestIAMServiceSingleResolveDerivedKeyUnknownAccess(t *testing.T) {
root := Account{Access: "root", Secret: "rootsecret", Role: RoleAdmin}
iam := NewIAMServiceSingle(root)
_, _, err := ResolveDerivedKey(iam, root, "NOSUCHKEYID0000000", "", "20260928", "us-east-1", sigv4auth.ServiceS3)
assert.Equal(t, ErrNoSuchUser, err)
}
func TestIAMServiceSingleResolveAccounts(t *testing.T) {
iam := NewIAMServiceSingle(Account{Access: "root", Secret: "rootsecret", Role: RoleAdmin})
missing, err := iam.ResolveAccounts([]string{"root", "user1", "user2"})
assert.NoError(t, err)
assert.Equal(t, []string{"user1", "user2"}, missing)
}