Skip to content

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

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

api: list-zones: do not send auth header#14
natalie-o-perret merged 1 commit into
mainfrom
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

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

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.

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 added a commit 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 natalie-o-perret force-pushed the fix/list-zones-no-iam-check branch from 792cfdd to 3e0c373 Compare June 15, 2026 15:47
@natalie-o-perret natalie-o-perret requested a review from a team June 15, 2026 15:47
@natalie-o-perret natalie-o-perret changed the title fix: skip Authorization header for list-zones api: list-zones: do not send auth header Jun 15, 2026
natalie-o-perret added a commit that referenced this pull request Jun 15, 2026
Resolves conflicts introduced by master regen commits. Re-applies
x-skip-auth: true on list-zones in api/openapi.yaml, hand-patches
the regenerated listZonesRequestBuilder to wrap signature and
Authorization header in a credentials != null guard. sdk/README.md
takes master's build-date stamp. sdk/api/openapi.yaml auto-merged
cleanly with the x-skip-auth extension preserved.

Refs: #14
@natalie-o-perret natalie-o-perret marked this pull request as ready for review June 15, 2026 16:02
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 natalie-o-perret force-pushed the fix/list-zones-no-iam-check branch from b2a3353 to 4b16220 Compare June 15, 2026 16:05
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 natalie-o-perret merged commit 431e869 into main Jun 16, 2026
2 checks passed
@natalie-o-perret natalie-o-perret deleted the fix/list-zones-no-iam-check branch June 16, 2026 11:01
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