Commit Graph
2686 Commits
Author SHA1 Message Date
Ben McClellandandGitHub 6fff0435f7 Merge pull request #2337 from versity/dependabot/github_actions/actions/setup-go-7
chore(deps): bump actions/setup-go from 6 to 7
2026-08-31 15:30:58 -07:00
Ben McClellandandGitHub 7bfb0f3b16 Merge pull request #2303 from versity/test/website_delete
test: website deletion, re-add s3 config, versitygw customization
2026-08-31 15:30:17 -07:00
Ben McClellandandGitHub 9a03856e66 Merge pull request #2341 from versity/ben/rdma-exclude
chore: add rdma/librcserver.a to .gitignore
2026-08-31 15:28:21 -07:00
Luke McCrone d62052b2be test: allow versitygw command customization, website testing, s3 config fix 2026-08-31 18:42:23 -03:00
Ben McClelland 87fc1b9a15 chore: add rdma/librcserver.a to .gitignore 2026-08-31 14:38:03 -07:00
Ben McClellandandGitHub e935440092 Merge pull request #2335 from versity/sis/getbucketversioning-access-control
feat: govern GetBucketVersioning with the regular access checks
2026-08-31 14:13:49 -07:00
dependabot[bot]andGitHub 77aa23b491 chore(deps): bump actions/setup-go from 6 to 7
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 6 to 7.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-31 21:06:23 +00:00
Ben McClellandandGitHub caa7ad5929 Merge pull request #2333 from potatogim/rdma-rc-go-binding
rdma: add the Go binding for the RC session server
2026-08-31 13:41:43 -07:00
Jihyeon GimandBen McClelland c281008632 rdma: add the Go binding for the RC session server
Bind the RC session server archive through cgo: Init opens the
verbs device with the resource limits, and the RCSvc wrapper
carries the admission gate handlers use around every session
call (TryEnter/Leave), a service-lifetime context that Close
cancels so in-flight handler I/O unblocks during shutdown, and
an idempotent Close that marks every session for reaping, waits
for admitted calls to drain, and destroys the server.

The rest of the surface maps the C ABI one-to-one: prepare,
ready (with the transfer outcome returned atomically in the
reply), staging borrow/finish, the put-view handoff, session
introspection, and cancel. Non-linux or non-cgo builds compile
against a stub so the package is portable.

Nothing imports the package yet; the gateway integration that
links and exercises it follows.

Signed-off-by: Jihyeon Gim <potatogim@potatogim.net>
2026-08-31 13:22:35 -07:00
Ben McClellandandGitHub bdad21a3f5 Merge pull request #2332 from potatogim/rdma-rc-server-abi
rdma: add the RC session server C ABI
2026-08-31 13:22:13 -07:00
Jihyeon GimandBen McClelland 64fcfeed83 rdma: add the RC session server C ABI
Wrap the v2 session core with the server-side C ABI the gateway
binds to: prepare/ready/cancel session calls, staging leases for
GET side-loading, the put-view handoff for PUT commits, session
introspection, and the server lifecycle.

The ABI owns the parts that must be shared across sessions: the
verbs device handle, global and per-principal resource limits,
session accounting with consume-once handles keyed by epoch and
nonce, the completion reference that pins a session from the
READY claim until its finalizer, and the reaper that tears
transport objects down once every reference drains. A background
thread expires sessions past their prepare or execute deadlines
so abandoned sessions cannot pin the limits, and teardown
failures keep the affected verbs objects and device alive rather
than freeing memory the NIC may still reference.

A peer-busy READY rolls the claim back and re-arms the QP
through RESET so the client can retry the same session. The
vgwrdma target now links the archive built from these sources.

Signed-off-by: Jihyeon Gim <potatogim@potatogim.net>
2026-08-31 13:05:33 -07:00
Ben McClellandandGitHub 479b954b35 Merge pull request #2331 from potatogim/rdma-rc-v2-core
rdma: port the hipObject v2 RC session core
2026-08-31 13:01:41 -07:00
Ben McClellandandGitHub 43fae0e045 Merge pull request #2325 from potatogim/feat/iam-cache-fresh
auth: add GetUserAccountFresh to bypass the IAM cache
2026-08-31 12:37:57 -07:00
Ben McClellandandGitHub 635bf7b80b Merge pull request #2324 from mu-adnan/fix/post-object-default-content-type
fix: apply default Content-Type in POSTObject
2026-08-31 09:57:09 -07:00
niksis02 7dfea7a38b feat: govern GetBucketVersioning with the regular access checks
S3 explicitly documents this action as owner-only ("To retrieve the versioning state of a bucket, you must be the bucket owner." — https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketVersioning.html), and the handler enforced that with an extra auth.IsAdminOrOwner check on top of VerifyAccess. Real S3 behaves differently: verified against AWS that a bucket policy explicitly denying s3:GetBucketVersioning denies the bucket owner itself, and that an Allow grants the action to a principal that doesn't own the bucket. It goes through ordinary bucket policy/ACL evaluation like any other bucket subresource read, which is what the write side, PutBucketVersioning, already did here. Removes the extra check along with auth.IsAdminOrOwner, which had no other call site.
2026-08-31 16:47:49 +04:00
Jihyeon Gim efa0309da4 rdma: port the hipObject v2 RC session core
Port the hipObject v2 reliable-connection session core into
cuwrapper/rc: the session table and state machine, the wire
codec for the hipobj-rc-v2 headers, request parsing, the
injectable clock and randomness sources, the transport layer
(QP/CQ lifecycle, RTR/RTS transitions, staging registration),
the data phase (RDMA write with immediate for GET, receive with
immediate for PUT), the RDMA token codec, and the dynamically
loaded ibverbs shim (ibv-core.h plus the dlopen host binding).

The sources are a port of the upstream hipObject v2 core, kept
close to the original so the two trees can be diffed during
review. Nothing links against them yet; a Makefile rule builds
the objects into rdma/librcserver.a for the ABI layer that
follows.

Signed-off-by: Jihyeon Gim <potatogim@potatogim.net>
2026-08-30 00:00:29 +09:00
Jihyeon Gim ea9c1d62f2 auth: add GetUserAccountFresh to bypass the IAM cache
The cached GetUserAccount keeps serving a stale entry for the
cache TTL after the backing IAM service changes, which delays
credential revocation by up to the configured expiry.

Add GetUserAccountFresh to the IAM cache, which reads directly
from the underlying service and refreshes the cached entry with
the result. Callers that need revocations to take effect
immediately can use it instead of the cached path.

Signed-off-by: Jihyeon Gim <potatogim@potatogim.net>
2026-08-29 16:55:30 +09:00
Muhammad AdnanandGitHub e4eb54c61a Merge branch 'main' into fix/post-object-default-content-type 2026-08-29 12:08:44 +05:00
mu-adnan 072081508d fix: add integeration tests 2026-08-29 12:06:50 +05:00
Ben McClellandandGitHub 83b5e7041c Merge pull request #2323 from versity/ben/embed-supply-iam
feat: allow supplying an external IAM service implementation to embedgw
2026-08-28 15:14:37 -07:00
mu-adnan 6121d52778 fix: apply default Content-Type in POSTObject
Browser-based POST uploads (POST /{bucket}) read Content-Type straight out
of the form fields, so a form without a content-type field stored the object
with an empty Content-Type. On read, fasthttp substitutes its own default,
so the object came back as "text/plain; charset=utf-8" rather than just
missing a type.

Fall back to defaultContentType ("binary/octet-stream") when the form field
is absent or empty, matching PutObject, CopyObject and CreateMultipartUpload,
as well as AWS S3 and Ceph RGW.
2026-08-29 00:38:34 +05:00
Ben McClelland a8c5810bee feat: allow supplying an external IAM service implementation to embedgw
Add Config.IAMService (auth.IAMService) so embedders that already have
their own IAM implementation can inject it directly instead of relying
on one of the gateway's built-in backends (local dir, LDAP, Vault,
S3-backed, FreeIPA, or the standalone IAM service). When set, it takes
priority over all other IAM backend configuration and RunVersityGW
skips calling auth.New entirely.

This avoids forcing embedders to duplicate their own account store as
one of the built-in IAM backends just to satisfy the gateway's IAM
interface.
2026-08-28 11:57:49 -07:00
Ben McClellandandGitHub ed49d6c3c8 Merge pull request #2320 from versity/ben/fix-build
fix: build failure from conflicting merges
2026-08-28 10:17:22 -07:00
Ben McClelland fce9d9bf69 fix: build failure from conflicting merges 2026-08-28 09:56:40 -07:00
Ben McClellandandGitHub 4a37af4ed3 Merge pull request #2288 from cmer/chore/open-pr-against-main
fix(posix): make conditional PUT evaluation and publication atomic per key
2026-08-28 09:51:12 -07:00
Ben McClellandandGitHub 816b743a56 Merge pull request #2319 from versity/ben/file-perms
feat: add configurable file permissions for new objects
2026-08-28 09:31:03 -07:00
Kyd CaoandBen McClelland 45a532e6a6 feat: add configurable file permissions for new objects
Replace the hardcoded 0644 defaultFilePerm with a NewFilePerm option on
the posix and scoutfs backends, exposed as the --file-perms flag and
VGW_FILE_PERMS env var alongside the existing dir-perms option.

The mode passed to open() is masked by the process umask, so the
O_TMPFILE path now chmods explicitly to match the CreateTemp fallback
path and give new objects the configured mode regardless of umask.
2026-08-28 08:51:03 -07:00
Ben McClellandandGitHub f04bd6a068 Merge pull request #2314 from versity/sis/iam-user-tagging
feat: add IAM user tagging actions
2026-08-27 16:41:37 -07:00
Nils LegerandGitHub c638503b90 feat(azure): carry Azure blob marker in continuation token for pagination
* feat(azure): carry Azure blob marker in continuation token for pagination

Azure blob markers are opaque values only Azure may mint, so an S3 object
key can never be passed back to Azure as a listing marker. Paging the
underlying Azure listing with an S3 key therefore failed or re-scanned the
whole prefix on every page.

Introduce azMarkerToken, an opaque S3 continuation token that carries the
Azure marker alongside the last returned key: the Azure marker resumes the
blob listing where it stopped, and the last key filters out already-returned
entries. Tokens are versioned with a "vgw1." prefix; anything without it is
treated as a plain key, so tokens from older versions and hand-crafted
markers keep working. The shared listBlobs helper now backs both ListObjects
and ListObjectsV2, applying the S3 marker and delimiter client side.
ListObjectsV2 pages efficiently via the token; ListObjects (v1) has no token
to carry state and walks the prefix from the start each page.

Add unit tests (token round-trip, marker-resumed pagination, delimiter and
common-prefix handling, multipart filtering) driven by a fake Azure
container, and integration tests covering full and delimited pagination.

Signed-off-by: Nils Leger <nils.leger@getflip.com>

* fix: token is now bound to delimiter too

Signed-off-by: Nils Leger <nils.leger@getflip.com>

---------

Signed-off-by: Nils Leger <nils.leger@getflip.com>
2026-08-27 16:40:43 -07:00
Nils LegerandGitHub a780f3473a feat(azure): server-side copy with download+reupload fallback
* feat(azure): implement server-side copy with fallback

Add server-side object copy for the Azure backend using StartCopyFromURL, with a
fallback to download+reupload when server-side copy is unavailable. The copy
logic lives in backend/azure/copy.go and handles metadata, tagging and object
lock configurations.

The copy-source SAS service version is configurable via the --copy-sas-version
flag (AZ_COPY_SAS_VERSION) and defaults to the SDK version, so production is
unchanged. Endpoints that lag the SDK's SAS version (e.g. Azurite) cannot verify
a SAS signed with the newer version and can set an older one. On a metadata-COPY,
the internal website-redirect key is dropped from the destination to match the
download+reupload fallback.

Testing:
- Add CopyObject_cross_bucket_server_side_copy, which copies an object with data,
  user metadata, content-type and tags across two buckets and verifies all are
  preserved and an ETag is returned.
- Configure the Azurite functional-test gateway with AZ_COPY_SAS_VERSION and let
  Azurite trust its self-signed test certificate (NODE_EXTRA_CA_CERTS) so it can
  fetch the copy source from its own HTTPS endpoint, ensuring CI exercises the
  real server-side copy path instead of always falling back.

Signed-off-by: Nils Leger <nils.leger@getflip.com>

* docs: update copyright year

Signed-off-by: Nils Leger <nils.leger@getflip.com>

* fix: always fallback to download+upload whenever there is an error building the server-side copy URL

Signed-off-by: Nils Leger <nils.leger@getflip.com>

---------

Signed-off-by: Nils Leger <nils.leger@getflip.com>
2026-08-27 16:37:28 -07:00
Ben McClellandandGitHub 29bf076abc Merge pull request #2308 from versity/sis/iam-webui
feat: add standalone IAM support in WebGUI
2026-08-27 16:14:16 -07:00
niksis02 4901afe27b feat: add IAM OIDC provider tagging actions
Adds `TagOpenIDConnectProvider`, `UntagOpenIDConnectProvider` and `ListOpenIDConnectProviderTags` to the standalone IAM service, backed by both the internal and Vault storers. They follow the user and role tagging actions in most respects — the tag action merges into the provider's existing tags and rejects a repeated key, untag removal is idempotent, and the tag listing is sorted by key and paginated, with the per-request member count and the per-provider tag total enforced as separate quotas so replacing a tag on a provider already at the 50-tag cap still succeeds — but differ in the one respect IAM itself draws: OIDC provider tag keys are compared exactly, not case-insensitively. On a provider `env` and `ENV` are two independent tags, both may be supplied in a single request, only a byte-identical repeat is a duplicate (reported without the "Tag keys are case insensitive" note the user and role actions carry), and untagging `env` leaves `ENV` in place.

That distinction is now carried by `iamutil.TagKeyCase`, which `ParseTags` uses for duplicate detection and which `mergeTags`, `removeTags` and the tag listing's marker lookup use for key matching. `CreateOpenIDConnectProvider` moves onto the exact comparison too, so a provider created with case-differing tag keys keeps both.

All three actions are authorized against the target provider's ARN, so `aws:ResourceTag/<key>` reads the provider's own tags, and the tag and untag actions populate `aws:RequestTag/<key>` and `aws:TagKeys` respectively, so a tag-scoped policy Condition governs which tags a caller may set or remove. All three report a missing provider with the wording `DeleteOpenIDConnectProvider` uses rather than the one `GetOpenIDConnectProvider` uses, which is why the Vault provider read now takes the not-found error its calling action reports.

The WebGUI gains a Tags section in the OIDC provider manage view, replacing the read-only tag row, and the shared tag editor gains a case-sensitive mode that changes its duplicate-key check, its diffing of an edited set into an untag and tag pair, and the wording of its guidance.
2026-08-28 00:49:21 +04:00
niksis02 1bbcd64195 feat: add IAM role tagging actions
Adds `TagRole`, `UntagRole` and `ListRoleTags` to the standalone IAM service, backed by both the internal and Vault storers, with the same semantics the user tagging actions already have: tag keys are matched case-insensitively but stored case-preserving, TagRole merges into the role's existing tags and rejects duplicate keys, UntagRole removal is idempotent, and ListRoleTags is sorted by key and paginated. The per-request member count and the per-role tag total are enforced as separate quotas, so replacing a tag on a role already at the 50-tag cap still succeeds. Role tags and the tags of a user sharing the same name are independent sets.

All three actions are authorized against the target role's ARN, so `aws:ResourceTag/<key>` reads the role's own tags, and TagRole and UntagRole populate `aws:RequestTag/<key>` and `aws:TagKeys` respectively, so a tag-scoped policy Condition governs which tags a caller may set or remove.

The tag storage helpers are now shared between users and roles: `MaxTagsPerUser` becomes `MaxTagsPerResource`, `ListUserTagsOutput` becomes `ListTagsOutput`, and `paginateTags` takes the marker and page size directly instead of a user-specific input struct.

The WebGUI gains a Tags section in the IAM role manage view, reusing the tag editor the user view already uses, which applies a whole edited tag set as a single UntagRole and TagRole pair.

Also corrects the `roleName` length bound across every role action: it was validated against the 128-character user-lookup limit, where IAM caps role names at 64.
2026-08-28 00:49:20 +04:00
niksis02 26a54b33e9 feat: add IAM user tagging actions
Adds `TagUser`, `UntagUser` and `ListUserTags` to the standalone IAM service, backed by both the internal and Vault storers. Tag keys are matched case-insensitively but stored case-preserving, TagUser merges into the user's existing tags and rejects duplicate keys, UntagUser removal is idempotent, and ListUserTags is sorted by key and paginated. The per-request member count and the per-user tag total are enforced as separate quotas.

All three actions are authorized against the target user's ARN, and TagUser and UntagUser populate aws:RequestTag/<key> and aws:TagKeys respectively, so a tag-scoped policy Condition governs which tags a caller may set or remove.

The WebGUI gains a Tags section in the IAM user manage view, with an editor that applies a whole edited tag set as a single UntagUser and TagUser pair.

Also corrects two error shapes that never matched AWS: a half-supplied tag member now reports a ValidationError naming the member field instead of MissingParameter, and the maxItems bound check reports separate lower- and upper-bound errors across every IAM list action.
2026-08-28 00:49:20 +04:00
niksis02 abb3b27149 feat: add standalone IAM support in WebGUI
Gates bucket listing behind an identity policy, lets browsers reach the standalone IAM API, and turns the WebUI into a dashboard for S3, IAM, or both.

**Bucket listing.** `ListBuckets` is now gated by the new `s3:ListAllMyBuckets` action, evaluated against `arn:aws:s3:::*`. The request names no bucket, so only identity policies apply — there is no resource policy to combine with, which is the same shape `CreateBucket` already had, so both now share one identity-only evaluation path. Root and admin bypass it, and backends with no identity-policy layer keep listing as before since their listing is already narrowed to the caller's own buckets. The action is IAM-only and is deliberately absent from the bucket-policy action list.

**Fixed bucket ownership.** The standalone IAM client has no per-user ownership to express — accounts are all plain users, cannot be enumerated, and access is decided by policy rather than ACL — so it now implements `auth.FixedBucketOwner` and every bucket is owned by root. Bucket creation stops resolving an owner, `ListBuckets` returns every bucket to every caller (what they may then do with one stays a per-request policy decision), and the admin `ChangeBucketOwner` reports method-not-supported. Other IAM backends are untouched.

**IAM service CORS.** `--cors-allow-origin` now applies to the `iam` command: it answers preflights and stamps the CORS headers, mirroring back the requested method and headers rather than enumerating the SigV4 header set. Without it no browser can reach the IAM API at all, so setting `--webui` without it falls back to `*` with a warning. The chart gets `iamServer.corsAllowOrigin`.

**WebUI.** New IAM pages for users, roles and OIDC providers, signing IAM/STS query-form requests directly from the browser. Navigation is capability-gated rather than role-gated: on sign-in the session probes the S3, admin and IAM endpoints independently and each page shows only what those credentials actually reach, so one build serves an IAM-only dashboard, an S3-only dashboard, and a combined one. The login page takes an optional IAM endpoint, seeded from the new `--webui-iam-gateways` (chart: `webui.iamGateways`) — never auto-detected, since the IAM service is a separate process. The WebUI can also be hosted by `versitygw iam` itself, for deployments with no S3 gateway behind it.

**The admin API is ignored once an IAM endpoint is in play.** The IAM service is then the user directory and bucket ownership is fixed, which leaves the admin API no job: the session is given no admin endpoint at all, its login field is hidden, `users.html` redirects to its IAM counterpart, and every admin-only surface stays off screen. Dashboard and Buckets remain available to any S3 session in such a deployment, running on the S3 and IAM APIs alone and surfacing each denial per action instead of redirecting.

Also fixes two WebUI bugs: embedded assets went out with a zero modification time and no `Cache-Control`, so browsers treated them as fresh for centuries and an upgraded gateway served new HTML against stale JS — they now revalidate against an ETag; and the login page's advanced-options section clipped its last field, since it animated to a height named in the stylesheet rather than the one it measures now.

**Usage**

IAM-only dashboard, served by the IAM service:

    versitygw iam --port :7076 --webui :8080 --cors-allow-origin http://localhost:8080/

IAM + S3, dashboard served by the IAM service — point it at the gateway with `--webui-gateways`, and let the gateway accept the dashboard's origin:

    versitygw iam --port :7076 --webui :8080 --webui-gateways http://localhost:7070/ --cors-allow-origin http://localhost:8080/
    versitygw --port :7070 --cors-allow-origin http://localhost:8080/ posix /data

IAM + S3, dashboard served by the S3 gateway — point it at the IAM service with `--webui-iam-gateways`, and let the IAM service accept the dashboard's origin:

    versitygw --port :7070 --webui :8080 --webui-iam-gateways http://localhost:7076/ posix /data
    versitygw iam --port :7076 --cors-allow-origin http://localhost:8080/
2026-08-27 20:28:51 +04:00
Ben McClellandandGitHub 61f1d1c9c8 Merge pull request #2293 from lhjnano/fix/getbucketversioning-empty-config
fix(posix): return empty config for GetBucketVersioning when unconfigured
2026-08-26 21:22:24 -07:00
Ben McClellandandGitHub 12c8d52e22 Merge pull request #2296 from versity/sis/iam-helm
feat: add Helm chart support for the standalone IAM service
2026-08-26 15:14:35 -07:00
Ben McClellandandGitHub 1cf4361150 Merge pull request #2315 from versity/dependabot/go_modules/dev-dependencies-9929f99704
chore(deps): bump the dev-dependencies group across 1 directory with 20 updates
2026-08-26 08:10:11 -07:00
dependabot[bot]andGitHub ea8233c05f chore(deps): bump the dev-dependencies group across 1 directory with 20 updates
Bumps the dev-dependencies group with 9 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [github.com/DataDog/datadog-go/v5](https://github.com/DataDog/datadog-go) | `5.9.0` | `5.9.1` |
| [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) | `1.32.37` | `1.32.38` |
| [github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager](https://github.com/aws/aws-sdk-go-v2) | `0.3.13` | `0.3.15` |
| [github.com/aws/smithy-go](https://github.com/aws/smithy-go) | `1.27.8` | `1.27.9` |
| [github.com/rabbitmq/amqp091-go](https://github.com/rabbitmq/amqp091-go) | `1.13.0` | `1.14.0` |
| [github.com/stretchr/testify](https://github.com/stretchr/testify) | `1.12.0` | `1.12.1` |
| [github.com/AzureAD/microsoft-authentication-library-for-go](https://github.com/AzureAD/microsoft-authentication-library-for-go) | `1.8.0` | `1.9.0` |
| [github.com/gofiber/utils/v2](https://github.com/gofiber/utils) | `2.4.1` | `2.4.2` |
| [github.com/pierrec/lz4/v4](https://github.com/pierrec/lz4) | `4.1.28` | `4.1.29` |



Updates `github.com/DataDog/datadog-go/v5` from 5.9.0 to 5.9.1
- [Release notes](https://github.com/DataDog/datadog-go/releases)
- [Changelog](https://github.com/DataDog/datadog-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/DataDog/datadog-go/compare/v5.9.0...v5.9.1)

Updates `github.com/aws/aws-sdk-go-v2/config` from 1.32.37 to 1.32.38
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.32.37...config/v1.32.38)

Updates `github.com/aws/aws-sdk-go-v2/credentials` from 1.19.36 to 1.19.37
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/credentials/v1.19.36...credentials/v1.19.37)

Updates `github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager` from 0.3.13 to 0.3.15
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/feature/s3/transfermanager/v0.3.13...feature/s3/transfermanager/v0.3.15)

Updates `github.com/aws/aws-sdk-go-v2/service/s3` from 1.107.2 to 1.107.3
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/s3/v1.107.2...service/s3/v1.107.3)

Updates `github.com/aws/aws-sdk-go-v2/service/sts` from 1.45.6 to 1.45.7
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/sts/v1.45.6...service/sts/v1.45.7)

Updates `github.com/aws/smithy-go` from 1.27.8 to 1.27.9
- [Release notes](https://github.com/aws/smithy-go/releases)
- [Changelog](https://github.com/aws/smithy-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/aws/smithy-go/compare/v1.27.8...v1.27.9)

Updates `github.com/rabbitmq/amqp091-go` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/rabbitmq/amqp091-go/releases)
- [Changelog](https://github.com/rabbitmq/amqp091-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rabbitmq/amqp091-go/compare/v1.13.0...v1.14.0)

Updates `github.com/stretchr/testify` from 1.12.0 to 1.12.1
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.12.0...v1.12.1)

Updates `github.com/AzureAD/microsoft-authentication-library-for-go` from 1.8.0 to 1.9.0
- [Release notes](https://github.com/AzureAD/microsoft-authentication-library-for-go/releases)
- [Changelog](https://github.com/AzureAD/microsoft-authentication-library-for-go/blob/main/changelog.md)
- [Commits](https://github.com/AzureAD/microsoft-authentication-library-for-go/compare/1.8.0...v1.9.0)

Updates `github.com/aws/aws-sdk-go-v2/feature/ec2/imds` from 1.18.37 to 1.18.38
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.18.37...config/v1.18.38)

Updates `github.com/aws/aws-sdk-go-v2/internal/v4a` from 1.4.38 to 1.4.39
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/internal/v4a/v1.4.38...internal/v4a/v1.4.39)

Updates `github.com/aws/aws-sdk-go-v2/service/internal/checksum` from 1.9.30 to 1.9.31
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/internal/checksum/v1.9.30...service/internal/checksum/v1.9.31)

Updates `github.com/aws/aws-sdk-go-v2/service/internal/presigned-url` from 1.13.37 to 1.13.38
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/credentials/v1.13.37...credentials/v1.13.38)

Updates `github.com/aws/aws-sdk-go-v2/service/internal/s3shared` from 1.19.38 to 1.19.39
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/credentials/v1.19.38...service/internal/s3shared/v1.19.39)

Updates `github.com/aws/aws-sdk-go-v2/service/signin` from 1.5.6 to 1.5.7
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/evs/v1.5.6...service/mpa/v1.5.7)

Updates `github.com/aws/aws-sdk-go-v2/service/sso` from 1.33.6 to 1.33.7
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/fms/v1.33.6...service/ebs/v1.33.7)

Updates `github.com/aws/aws-sdk-go-v2/service/ssooidc` from 1.38.6 to 1.38.7
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/sts/v1.38.6...service/sts/v1.38.7)

Updates `github.com/gofiber/utils/v2` from 2.4.1 to 2.4.2
- [Release notes](https://github.com/gofiber/utils/releases)
- [Commits](https://github.com/gofiber/utils/compare/v2.4.1...v2.4.2)

Updates `github.com/pierrec/lz4/v4` from 4.1.28 to 4.1.29
- [Release notes](https://github.com/pierrec/lz4/releases)
- [Commits](https://github.com/pierrec/lz4/compare/v4.1.28...v4.1.29)

---
updated-dependencies:
- dependency-name: github.com/DataDog/datadog-go/v5
  dependency-version: 5.9.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dev-dependencies
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-version: 1.32.38
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dev-dependencies
- dependency-name: github.com/aws/aws-sdk-go-v2/credentials
  dependency-version: 1.19.37
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dev-dependencies
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager
  dependency-version: 0.3.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dev-dependencies
- dependency-name: github.com/aws/aws-sdk-go-v2/service/s3
  dependency-version: 1.107.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dev-dependencies
- dependency-name: github.com/aws/aws-sdk-go-v2/service/sts
  dependency-version: 1.45.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dev-dependencies
- dependency-name: github.com/aws/smithy-go
  dependency-version: 1.27.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dev-dependencies
- dependency-name: github.com/rabbitmq/amqp091-go
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dev-dependencies
- dependency-name: github.com/stretchr/testify
  dependency-version: 1.12.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dev-dependencies
- dependency-name: github.com/AzureAD/microsoft-authentication-library-for-go
  dependency-version: 1.9.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: dev-dependencies
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/ec2/imds
  dependency-version: 1.18.38
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: dev-dependencies
- dependency-name: github.com/aws/aws-sdk-go-v2/internal/v4a
  dependency-version: 1.4.39
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: dev-dependencies
- dependency-name: github.com/aws/aws-sdk-go-v2/service/internal/checksum
  dependency-version: 1.9.31
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: dev-dependencies
- dependency-name: github.com/aws/aws-sdk-go-v2/service/internal/presigned-url
  dependency-version: 1.13.38
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: dev-dependencies
- dependency-name: github.com/aws/aws-sdk-go-v2/service/internal/s3shared
  dependency-version: 1.19.39
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: dev-dependencies
- dependency-name: github.com/aws/aws-sdk-go-v2/service/signin
  dependency-version: 1.5.7
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: dev-dependencies
- dependency-name: github.com/aws/aws-sdk-go-v2/service/sso
  dependency-version: 1.33.7
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: dev-dependencies
- dependency-name: github.com/aws/aws-sdk-go-v2/service/ssooidc
  dependency-version: 1.38.7
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: dev-dependencies
- dependency-name: github.com/gofiber/utils/v2
  dependency-version: 2.4.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: dev-dependencies
- dependency-name: github.com/pierrec/lz4/v4
  dependency-version: 4.1.29
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: dev-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-25 21:40:42 +00:00
Ben McClellandandGitHub c1fc892a15 Merge pull request #2221 from versity/sis/aws-compatible-iam
feat: add AWS-compatible standalone IAM service
2026-08-25 14:20:00 -07:00
Ben McClellandandGitHub 3fff8193dc Merge pull request #2312 from versity/dependabot/github_actions/github/codeql-action-4.37.8
chore(deps): bump github/codeql-action from 4.37.7 to 4.37.8
2026-08-25 11:32:49 -07:00
HeonJe Lee b83f5d903b fix(posix): return empty config for GetBucketVersioning when unconfigured
Validate bucket existence before checking the versioning state so a
missing bucket still yields 404 NoSuchBucket. When no versioning
directory is configured, respond with 200 and an empty configuration
instead of VersioningNotConfigured, matching AWS semantics. GUI clients
(e.g. S3 Browser) poll this API while browsing buckets and were
failing on default deployments. PutBucketVersioning still rejects with
VersioningNotConfigured.

Fix a swapped test body between the Get/Put "not configured" cases,
add integration coverage for GetBucketVersioning on a non-existent
bucket, and add backend/posix unit tests guarding the validation order
and the empty 200 response.

Ref: exastor/versitygw!3
2026-08-25 11:42:03 +09:00
niksis02 7b6b816df9 feat: add Helm chart support for the standalone IAM service
This adds a new iamServer Deployment, split public and private Services, a PersistentVolumeClaim, and cert-manager Certificate resources so the standalone versitygw iam API server can be deployed directly from this chart, independently scalable from the S3 gateway and backed by either internal file storage or HashiCorp Vault, with Vault auth credentials and Vault TLS material kept in separate Kubernetes secrets. The gateway side gains iam.type=standalone client wiring that reaches the IAM service over its private mTLS endpoint, with certificates supplied either through an existing secret or auto-provisioned via cert-manager using a shared CA-type issuer so both peers can verify each other from their own certificate's ca.crt, and the chart auto-targets the in-chart service when no external endpoint is configured. gateway.logLevel and iamServer.logLevel replace the old boolean debug flag with the silent, debug, and unsafe levels the binary now supports, docker-entrypoint.sh gained iam as a recognized VGW_BACKEND value so the new deployment can start through the existing entrypoint, NetworkPolicy resources were corrected to use proper peer lists and to default to deny instead of allow when no ingress rules are configured, pod and Deployment selector labels were separated between the gateway and the IAM server to prevent them from matching each other's Services, and a battery of template time validation guards was added to fail fast on invalid combinations such as multiple replicas against the internal file store or a missing certificate for a TCP private endpoint, together with expanded helm lint coverage in CI for these new configurations.
2026-08-25 01:55:18 +04:00
niksis02 a4d4519ffe feat: version the private IAM protocol between gateway and standalone service
The S3 gateway and the standalone IAM service exchange authorization decisions over the private endpoints, where a version skew is silently unsafe in both directions: an older service drops a request field it does not know (a `Condition` block, say) and evaluates fail-open, while an older gateway ignores a response field it does not know and misses a deny the service intended. Neither side could previously detect either case.

Both peers now declare a protocol version on every exchange via the `X-Vgw-Private-Protocol` header — the gateway on each request, the service on each response, error responses included — and each refuses a peer it cannot serve safely. The service rejects a gateway below `MinClientProtocol` with a `ProtocolMismatch` code; the gateway rejects a service older than the `ProtocolVersion` it speaks, and rejects a response carrying no version at all, since no build of this protocol omits the header and something else answering on that address should not be interpreted as an IAM decision. `ParseProtocolVersion` is shared by both sides and deliberately strict: an unreadable value is a mismatch, never an assumed default.

A new root-signed `/private/version` endpoint reports the protocol version, the minimum client the service will serve, and the build tag (`WithPrivateServerVersion`). It is exempt from the service's own client-version check so it can still answer a gateway the service refuses — which is how that gateway learns why. Being authenticated like every other private endpoint, it also lets the gateway's startup probe verify its own credential and its mTLS transport in the same round trip.

The gateway probes it once in `NewIAMServiceStandalone` rather than discovering a skew as an opaque per-request 500. An incompatible service is fatal after a 30s window, since a gateway that cannot authorize a single request is more useful refusing to start with the reason in its log; an unreachable one is only a warning, because the two processes legitimately start in parallel and every request checks the version regardless. Only conditions that can resolve on their own are retried — a rejected credential is reported immediately.
2026-08-25 01:41:12 +04:00
niksis02 2147a0c304 feat: integrate standalone IAM service with S3 gateway for identity-based policy enforcement
Fixes #1327
Fixes #1567
Closes #2264

Wires the S3 gateway up to the standalone IAM service so identity policies, not just bucket policies and ACLs, are enforced on the S3 data plane. The gateway authenticates SigV4 requests by calling new private derive-signing-key and resolve-identity endpoints on the IAM service instead of holding secrets itself, and evaluates identity policy through the same PolicyEvaluator path added to auth.VerifyAccess, combined with the bucket policy using explicit-deny-wins precedence. The private endpoints are served over their own mTLS listener (new iamapi/private package, genmtlscerts.sh to generate test material, and client-cert support in internal/netutil), separate from the public IAM API. As part of this the vendored aws/signer/v4 package is deleted and replaced by a pure-Go SigV4 implementation in internal/sigv4auth, which now reads canonical request data directly off the fiber.Ctx instead of reconstructing an http.Request, and is shared by both the S3 request-signing verification and the new private-endpoint signing.

DeleteObjects moves from an all-or-nothing authorization check to true partial success: VerifyObjectsAccess evaluates every object in a batch independently against both the identity policy and any object lock, so a denial or a locked object only removes that key from the batch instead of failing the whole request. It also batches the identity-policy round trip and the bucket-policy fetch once per request rather than once per object, and separates plain deletes from versioned ones since a versioned delete needs s3:DeleteObjectVersion rather than s3:DeleteObject. Object lock handling got a few correctness fixes alongside this: a bypass is now modeled as BypassNone/BypassRequested/BypassOverwrite rather than a single bool, because root's blanket ability to override a GOVERNANCE retention should only apply when the client actually asked to bypass it (DeleteObject/DeleteObjects/PutObjectRetention), not when the gateway is silently replacing a locked object via an overwrite, which needs the permission from everyone including root. Retention changes are now correctly classified as an extension (allowed under plain s3:PutObjectRetention) versus a weakening (date or mode change, which needs the bypass permission), and a COMPLIANCE lock can never be weakened by anyone regardless of permissions, matching AWS. Separately, VerifyObjectCopyAccess had a readonly-mode gap: it returned early for root/admin before ever calling VerifyAccess, so the readonly check inside VerifyAccess never ran for them on CopyObject; access checks are now ordered so the readonly gate always applies before any root/admin bypass, for copy as well as every other write path.

Bucket policies also gained Condition block support, via a new shared internal/condition package moved out of the IAM policy package since both bucket and identity policies share the same evaluation semantics. It implements the full AWS operator set — String{Equals,NotEquals,EqualsIgnoreCase,NotEqualsIgnoreCase,Like,NotLike}, Numeric{Equals,NotEquals,LessThan,LessThanEquals,GreaterThan,GreaterThanEquals}, Date{Equals,NotEquals,LessThan,LessThanEquals,GreaterThan,GreaterThanEquals}, Bool, BinaryEquals, Arn{Equals,Like,NotEquals,NotLike}, IpAddress/NotIpAddress, and Null — along with the ForAllValues/ForAnyValue set qualifiers and the IfExists modifier. A new requestConditionContext builds the per-request keys a bucket policy's Condition block can reference — aws:SourceIp, aws:SecureTransport, aws:CurrentTime, aws:EpochTime, aws:UserAgent, aws:Referer, s3:prefix, s3:delimiter, s3:max-keys, s3:x-amz-acl, s3:VersionId — following AWS's own per-action rules for which keys a given S3 operation actually populates. Identity-derived keys such as aws:PrincipalArn and aws:username are deliberately left unwired here, since the gateway has no way to know them; the standalone IAM service fills those in itself when it evaluates an identity policy.

Also added new integration test suites for S3-side IAM: s3_iam_access_control.go and s3_iam_session_access_control.go cover identity-policy enforcement and session-credential requests against real S3 operations, alongside expanded OIDC/web-identity coverage and a new runoidctests.sh runner wired into the OIDC GitHub Actions workflow.
2026-08-25 01:07:36 +04:00
niksis02 2e22a42324 feat: add live GitHub OIDC end-to-end test for AssumeRoleWithWebIdentity
Add IAMAssumeRoleWithWebIdentity_github_oidc_live, the only web-identity test that exercises AssumeRoleWithWebIdentity against a real external OIDC provider end-to-end: GitHub Actions' own issuer, with real discovery-document fetch, JWKS fetch, RS256 signature verification, claims mapping, and session credential issuance. Every other web-identity test in the suite uses a fake token that never reaches real signature verification. The test registers a throwaway OIDC provider and trust role scoped to this repo (via a distinct test audience and repo-scoped sub condition), fetches a real ID token from GitHub's runtime endpoint, assumes the role, and confirms the issued session credentials work with a follow-up GetCallerIdentity call. It cleans up the role and provider unconditionally and skips itself when run outside a GitHub Actions job with id-token: write permission (e.g. local runs or fork PRs, where GitHub downgrades OIDC permissions to read-only).

Add functional-iam-oidc.yml to run this test in CI on push to main and on same-repo pull_request runs, isolated from the full iam suite since it's the only test needing id-token: write.

Add a SKIP counter and skipF() alongside the existing runF/passF/failF, and report it in the final RAN/PASS/FAIL summary, so a test opting out via skipF() (as this one does when OIDC env vars aren't present) is visible instead of silently absent from the count.
2026-08-25 01:07:33 +04:00
dependabot[bot]andGitHub ec61bc5cae chore(deps): bump github/codeql-action from 4.37.7 to 4.37.8
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.37.7 to 4.37.8.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v4.37.7...v4.37.8)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.37.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-24 21:07:21 +00:00
niksis02 ab2b816633 feat: add STS web identity federation, IAM policy Condition support, and access control enforcement
Implements the `AssumeRoleWithWebIdentity` and `GetCallerIdentity` STS actions, letting callers exchange an external OIDC token for temporary credentials scoped to an IAM role. Token handling covers JWT claim parsing, issuer/audience resolution (including `azp` override semantics), JWKS fetching and caching with `singleflight`-deduplicated refresh, and rate-limited forced refresh on unrecognized `kid` values. OIDC provider thumbprint fetching now performs a real TLS handshake verified against the system trust store and the provider hostname (previously `InsecureSkipVerify`), since the observed certificate is persisted as a long-lived trust anchor rather than used once and discarded; all discovery-document and JWKS fetches go through an SSRF-safe HTTP client with bounded redirects and response size.

Adds policy `Condition` block evaluation, supporting `String`, `Numeric`, `Date`, `Bool`, `BinaryEquals`, and `IpAddress` operators along with their `IfExists`/`Not` variants and `ForAllValues`/`ForAnyValues` set qualifiers, plus policy variable substitution (e.g. `${aws:username}`) in supported operators. Adds identity-based inline policy evaluation and a new IAM authorization middleware that authorizes each request against action, resource, and condition context together, applying the session-policy-intersects-role-policy semantics for assumed-role sessions.

Adds a new debug logger `--log-level` flag (`silent`/`debug`/`unsafe`), along with a tree-based XML masker that redacts secrets and tokens at the property level in logged request/response bodies instead of skipping the whole body. The old `--debug/VGW_DEBUG` flag is kept as a deprecated alias for `--log-level=debug`, printing a console warning that points users at `--log-level` for finer-grained control.

Fixes a Vault storage bug where CAS (check-and-set) writes always read the current document version as 0 because `kvVersion` asserted metadata as `float64` while the Vault client actually returns `json.Number`, causing every write past the first to be rejected as a concurrent modification. Also adds a constant-time `SecureCompare` for signature/token comparisons in sigv4 auth.

Adds an integration test suite (`iam_access_control.go`) covering IAM access control across user, role, and session identities.
2026-08-25 01:06:25 +04:00
niksis02 ec579ca841 feat: add IAM OIDC provider CRUD
Add support for `CreateOpenIDConnectProvider`, `GetOpenIDConnectProvider`, `ListOpenIDConnectProviders`, `DeleteOpenIDConnectProvider`, `AddClientIDToOpenIDConnectProvider`, `RemoveClientIDFromOpenIDConnectProvider`, and `UpdateOpenIDConnectProviderThumbprint` on both the internal and Vault storage backends, rounding out the standalone IAM service with the same OIDC identity provider management AWS IAM exposes.

CreateOpenIDConnectProvider validates the issuer URL, enforces the client ID and per-provider client ID list limits, and accepts an optional ThumbprintList. When the caller omits ThumbprintList, the provider auto-fetches the thumbprint by opening an outbound TLS connection to the issuer URL and hashing its top-level CA certificate, matching real AWS behavior. This auto-fetch is configurable: it can be turned off with the `--disable-oidc-thumbprint-autofetch` CLI flag (or the `VGW_IAM_DISABLE_OIDC_THUMBPRINT_AUTOFETCH` environment variable) for restricted or air-gapped deployments where the IAM server shouldn't make outbound connections, in which case an omitted ThumbprintList is rejected instead. AddClientIDToOpenIDConnectProvider and RemoveClientIDFromOpenIDConnectProvider manage a provider's client ID list, and UpdateOpenIDConnectProviderThumbprint replaces its thumbprint list, all with the same length and format validation applied at creation time.

Provider ARNs are derived from the issuer URL, and GetOpenIDConnectProvider and DeleteOpenIDConnectProvider resolve providers by ARN, returning NoSuchEntity when a provider doesn't exist. ListOpenIDConnectProviders returns the full set of stored providers. These actions are wired into the IAM API router and given their own XML response types under iamapi/types, with a new iamapi/internal/iamutil package handling URL validation, thumbprint fetching and normalization, and ARN construction shared across the controller methods.
2026-08-25 01:03:22 +04:00
niksis02 c9ce6ab37c feat: add IAM role inline policy CRUD
Add support for the `PutRolePolicy`, `GetRolePolicy`, `DeleteRolePolicy`, and `ListRolePolicies` actions in the IAM-compatible gateway service, extending role management with the same inline-policy lifecycle already available for IAM users. `PutRolePolicy` validates the policy name and document, parses the document for AWS-compatible syntax and semantic errors (missing actions/resources, malformed ARNs, disallowed principals, duplicate statement IDs, and so on), and rejects documents once the role's aggregate inline-policy size would exceed `MaxInlinePolicyBytesPerRole` (10240 bytes, distinct from the 2048-byte quota enforced for users). Putting a policy under an existing name overwrites its document in place. `GetRolePolicy` and `DeleteRolePolicy` look up or remove a named inline policy from a role, returning a `NoSuchEntity` error when the role or the policy is not found. `ListRolePolicies` returns a role's inline policy names in sorted order with marker-based pagination.

These actions are implemented for both the internal file-backed store and the Vault-backed store, wired into the IAM API router, and given their own XML response types under `iamapi/types`. A new `NoSuchEntityRolePolicy` error was added to `iamapi/iamerr` to mirror the existing user-policy error.
2026-08-25 01:03:22 +04:00