Skip to content

v3: list-zones: do not send auth header - #767

Merged
natalie-o-perret merged 1 commit into
masterfrom
fix/list-zones-no-iam-check
Jun 15, 2026
Merged

v3: list-zones: do not send auth header#767
natalie-o-perret merged 1 commit into
masterfrom
fix/list-zones-no-iam-check

Conversation

@natalie-o-perret

@natalie-o-perret natalie-o-perret commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

Description

/zones is public but the server enforces IAM on authenticated requests, so a DBaaS-only key gets 403 for no reason.

RequestTmpl now has a SkipAuth bool field. When set, the generated function skips signRequest and sends no Authorization header. Operations opt in via x-skip-auth: true in the spec, so the guard survives future regenerations.

Snippet used to verify:

package main

import (
"context"
"fmt"
"os"

v3 "github.com/exoscale/egoscale/v3"
"github.com/exoscale/egoscale/v3/credentials"
)

func main() {
	creds := credentials.NewStaticCredentials(os.Getenv("EXO_KEY"), os.Getenv("EXO_SECRET"))
	client, _ := v3.NewClient(creds)
	zones, err := client.ListZones(context.Background())
	if err != nil {
		fmt.Fprintln(os.Stderr, "error:", err)
		os.Exit(1)
	}
	fmt.Printf("ok: %d zones\n", len(zones.Zones))
}

Or with the CLI (DBaaS-only profile, using any command that triggers a zone switch):

# before fix
$ exo dbaas update --valkey-ip-filter 1.2.3.4/32 valkey-test-fix -z de-muc-1
error: unable to create client: switch client zone v3: get zone api endpoint: list zones: ListZones: http response: Forbidden: Forbidden by role policy for compute

# after fix
$ exo dbaas update --valkey-ip-filter 1.2.3.4/32 valkey-test-fix -z de-muc-1
 ✔  Updating DBaaS Valkey service "valkey-test-fix"  0s

Go before (master, DBaaS-only key):

error: ListZones: http response: Forbidden: Invalid request signature

Go after (this branch, same key):

ok: 8 zones
  - ch-gva-2
  - ch-dk-2
  - at-vie-1
  - de-fra-1
  - bg-sof-1
  - de-muc-1
  - at-vie-2
  - hr-zag-1

Related: exoscale/python-exoscale#90, exoscale/exoscale-sdk-java#14

Checklist

(For exoscale contributors)

  • Changelog updated (under Unreleased block)

Note

AI-assisted.

@natalie-o-perret

Copy link
Copy Markdown
Contributor Author

[SC-176979]

natalie-o-perret added a commit that referenced this pull request Jun 15, 2026
Resolve CHANGELOG conflict by keeping the Unreleased entry above
master's 3.1.38/3.1.37 release blocks. Regenerated files from
master already include the SkipAuth change, so no further code
edits were required.

Refs: #767
natalie-o-perret added a commit that referenced this pull request Jun 15, 2026
Resolves a new conflict introduced by master commits #780 and #783.
CHANGELOG: keep the Unreleased entry, add a 3.1.39 block for #783 above
the existing 3.1.38/3.1.37. helpers.go auto-merged cleanly.

Refs: #767
The /zone endpoint enforces IAM role policies on authenticated requests.
Restricted keys (e.g. DBaaS-only) get 403 even though the endpoint
returns public data.

Skip signRequest for list-zones so the call always succeeds.

RequestTmpl gains a SkipAuth bool. The generator sets it for
list-zones and the template wraps signRequest in {{ if not .SkipAuth }}.
Future regens keep the guard as long as the hardcode stays; an
upstream x-skip-auth extension in the OpenAPI spec would be the
cleaner long-term home for the opt-in.

Refs: #767
@natalie-o-perret
natalie-o-perret force-pushed the fix/list-zones-no-iam-check branch from cdaf0db to 86e355b Compare June 15, 2026 15:31
@natalie-o-perret
natalie-o-perret marked this pull request as ready for review June 15, 2026 15:34
@natalie-o-perret
natalie-o-perret requested review from a team and kobajagi June 15, 2026 15:34
@natalie-o-perret
natalie-o-perret merged commit ee33806 into master Jun 15, 2026
6 checks passed
@natalie-o-perret
natalie-o-perret deleted the fix/list-zones-no-iam-check branch June 15, 2026 15:42
natalie-o-perret added a commit to exoscale/exoscale-sdk-java that referenced this pull request Jun 15, 2026
The /zone endpoint enforces IAM policies on authenticated requests,
causing 403 for restricted keys (e.g. DBaaS-only) even though the
endpoint returns public data.

Add x-skip-auth to the list-zones operation in the spec. The
api.mustache template wraps the signing block in a
{{^vendorExtensions.x-skip-auth}} guard, so the generated
listZonesRequestBuilder omits the Authorization header.

The update workflow injects the extension after fetching the spec,
so the guard survives future automated spec updates. pom.xml now
reads the local api/openapi.yaml instead of fetching the spec at
build time, consistent with the workflow change.

Same fix applied to the Go SDK: exoscale/egoscale#767
Same fix applied to the Python SDK: exoscale/python-exoscale#90

Refs: #14
natalie-o-perret added a commit to exoscale/exoscale-sdk-java that referenced this pull request Jun 15, 2026
The /zone endpoint enforces IAM policies on authenticated requests,
causing 403 for restricted keys (e.g. DBaaS-only) even though the
endpoint returns public data.

Add x-skip-auth to the list-zones operation in the spec. The
api.mustache template wraps the signing block in a
{{^vendorExtensions.x-skip-auth}} guard, so the generated
listZonesRequestBuilder omits the Authorization header.

The update workflow injects the extension after fetching the spec,
so the guard survives future automated spec updates. pom.xml now
reads the local api/openapi.yaml instead of fetching the spec at
build time, consistent with the workflow change.

Same fix applied to the Go SDK: exoscale/egoscale#767
Same fix applied to the Python SDK: exoscale/python-exoscale#90

Refs: #14
natalie-o-perret added a commit to exoscale/cli that referenced this pull request Jun 16, 2026
# Description

Bumps `github.com/exoscale/egoscale/v3` to v3.1.40.

Picks up
[exoscale/egoscale#767](exoscale/egoscale#767):
`ListZones` no longer sends an `Authorization` header, so DBaaS-only IAM
keys (and other restricted keys) can switch zones without hitting 403 on
the public `/zone` endpoint.

This also drags in the regenerated AI API key surface (path/types) and
the enum separator fix from
[exoscale/egoscale#783](exoscale/egoscale#783).
No CLI source changes are required: `go build`, `go vet` and `go test
-run=^$ ./...` all pass cleanly against the new vendor tree.

The vendored `Client.ListZones` now skips `signRequest`, which is the
change that ships in v3.1.40 (the `v3.1.39` tag pre-dates #767: v3.1.40
was cut specifically to include it).

## Related issue

- [exoscale/egoscale#767](exoscale/egoscale#767)

## Changes

- `go.mod`, `go.sum`: pin `github.com/exoscale/egoscale/v3` from
`v3.1.36-0.20260424083744-33446130ebd9` to `v3.1.40`
- `vendor/...`: regenerated via `go mod vendor` (the `v3/operations.go`
`ListZones` body now skips `signRequest`)
- `CHANGELOG.md`: add Bug fixes entry under Unreleased

## Checklist

(For exoscale contributors)

* [x] Changelog updated (under *Unreleased* block)
* [x] Testing

## Testing

- `go build ./...`
- `go vet ./...`
- `go test -run=^$ ./...` (compiles all test packages)

## Notes for reviewers

> [!NOTE]
> AI-assisted.
natalie-o-perret added a commit to exoscale/python-exoscale that referenced this pull request Jun 16, 2026
`/zone` is public but the server enforces IAM on authenticated requests,
so a DBaaS-only key gets 403 for no reason.

In `_call_operation`, when the operation is `list-zones`, the request is
sent via a plain `requests.request` without credentials. No IAM check
fires and all zones come back.

**Snippet used to verify:**

```python
from exoscale.api.v2 import Client

client = Client(key=key, secret=secret, zone="ch-gva-2")
result = client.list_zones()
zones = result["zones"]
print(f"ok: {len(zones)} zones")
for z in zones:
    print(f"  - {z['name']}")
```

**Before** (master, DBaaS-only key):
```
exoscale.api.exceptions.ExoscaleAPIAuthException: Authentication error 403: {"message":"Invalid request signature"}
```

**After** (this branch, same key):
```
ok: 8 zones
  - ch-gva-2
  - ch-dk-2
  - at-vie-1
  - de-fra-1
  - bg-sof-1
  - de-muc-1
  - at-vie-2
  - hr-zag-1
```

Related: exoscale/egoscale#767, exoscale/exoscale-sdk-java#14

---

> [!NOTE]
> AI-assisted.
natalie-o-perret added a commit to exoscale/exoscale-sdk-java that referenced this pull request Jun 16, 2026
`/zone` is public but the server enforces IAM on authenticated requests,
so a DBaaS-only key gets 403 for no reason.

The `api.mustache` template wraps the signing block in a
`{{^vendorExtensions.x-skip-auth}}` guard, so the generated
`listZonesRequestBuilder` sends no `Authorization` header.

The update workflow injects the extension after fetching the upstream
spec, so the guard survives future automated spec updates.

**Snippet used to verify:**

```java
import com.exoscale.sdk.api.ExoscaleApi;
import com.exoscale.sdk.client.ApiClient;
import com.exoscale.sdk.client.Credentials;
import com.exoscale.sdk.model.ListZones200Response;
import com.exoscale.sdk.model.Zone;

Credentials creds = new Credentials(key, secret);
ApiClient apiClient = new ApiClient(creds);
apiClient.updateBaseUri("https://api-ch-gva-2.exoscale.com/v2");

ExoscaleApi api = new ExoscaleApi(apiClient);
ListZones200Response resp = api.listZones();
System.out.printf("ok: %d zones%n", resp.getZones().size());
for (Zone z : resp.getZones()) {
    System.out.printf("  - %s%n", z.getName());
}
```

**Before** (main, DBaaS-only key):
```
error 403: {"message":"Invalid request signature"}
```

**After** (this branch, same key):
```
ok: 8 zones
  - ch-gva-2
  - ch-dk-2
  - at-vie-1
  - de-fra-1
  - bg-sof-1
  - de-muc-1
  - at-vie-2
  - hr-zag-1
```

Related: exoscale/egoscale#767, exoscale/python-exoscale#90

---

> [!NOTE]
> AI-assisted.

Co-authored-by: natalie-o-perret <natalie-o-perret@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants