Skip to content

api: list-zones: do not send auth header#90

Open
natalie-o-perret wants to merge 1 commit into
masterfrom
fix/list-zones-no-iam-check
Open

api: list-zones: do not send auth header#90
natalie-o-perret wants to merge 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

/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:

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.

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.

Skip credentials for list-zones so the call always succeeds.
natalie-o-perret added a commit to exoscale/egoscale that referenced this pull request Jun 15, 2026
# 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:**

```go
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)
- [x] Changelog updated (under Unreleased block)

---

> [!NOTE]
> AI-assisted.
@natalie-o-perret natalie-o-perret marked this pull request as ready for review June 15, 2026 15:45
@natalie-o-perret natalie-o-perret requested a review from a team June 15, 2026 15:45
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
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.

1 participant