feat(ovhcloud): accept a service account (OAuth2) as well as application keys (1.2.0)
The control panel does not offer application keys on every account — some can only create a SERVICE ACCOUNT, which authenticates with OAuth2 client credentials. An instance built that way could not talk to the API at all, which is a hard stop for anybody whose account is in that shape. Both schemes are now supported, and which one is used is decided by WHAT WAS FILLED IN rather than by a mode selector: a client_id and a client_secret mean the service account, anything else falls back to the signed scheme. One less field to get wrong, and every existing instance keeps working untouched. The API base is corrected to /v1 for a service account. The same routes answer under /1.0 and /v1, but a Bearer token sent to the legacy spelling fails in a way that reads as "bad credentials" — which sends somebody off to regenerate a perfectly good secret. An operator should not have to know that the spelling and the credential go together. Nothing in config_schema is required any more. The schema cannot express "one set or the other", and keeping the historical three required would refuse every service-account instance; the scripts refuse an instance with neither and name both sets, which is an error somebody can act on — where a form that will not submit is one they can only fight. Two things the shared block now caches for the life of the process, both of which matter on the ladder path that runs every time the rota turns: the access token (a token request in front of each of a dozen calls would triple the traffic) and the clock offset against OVH's time (it was a round trip per signed request). Verified offline for both schemes: the base URL each one talks to, the headers that land on the wire, the single token request, and the refusal when neither set is present. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TN1R4EnNFUV2Xwtd9q98tj
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
id: ovhcloud
|
||||
name: OVHcloud
|
||||
version: 1.1.0
|
||||
version: 1.2.0
|
||||
description: "OVHcloud (API v1) — cloud account and infrastructure visibility, plus VoIP on-call routing: read the account, list public cloud projects, list/read dedicated servers, and hold Riposte's on-call ladder in a telephony call queue so a client number reaches whoever is on duty without any channel on your own PBX. Signed application-key authentication; stdlib-only, no extra Python dependencies. (French vendor.)"
|
||||
changelog: "1.1.0 — On-call routing: set_oncall_ladder / get_oncall_ladder / list_calls, backed by a VoIP call queue (easyHunting). Riposte publishes the ordered on-call numbers and the carrier rings them in that order, so an inbound client call never crosses your own trunk and spends no simultaneous call on it. Needs the three telephony_* config fields; every other command is unchanged. | 1.0.0 — Initial release: get account, list cloud projects, list/get dedicated servers."
|
||||
changelog: "1.2.0 — Accept a SERVICE ACCOUNT (OAuth2 client credentials) as well as the historical application keys, because that is what the control panel offers on accounts where application keys are not available. Which scheme is used is decided by what you filled in, not by a mode selector, and an existing instance keeps working untouched. The API base is corrected to /v1 for a service account, since a Bearer token sent to the legacy /1.0 spelling fails in a way that reads as bad credentials. | 1.1.0 — On-call routing: set_oncall_ladder / get_oncall_ladder / list_calls, backed by a VoIP call queue (easyHunting). Riposte publishes the ordered on-call numbers and the carrier rings them in that order, so an inbound client call never crosses your own trunk and spends no simultaneous call on it. Needs the three telephony_* config fields; every other command is unchanged. | 1.0.0 — Initial release: get account, list cloud projects, list/get dedicated servers."
|
||||
category: cloud
|
||||
|
||||
# Per-instance configuration. Requests are signed (SHA-1) with the application
|
||||
@@ -13,16 +13,32 @@ config_schema:
|
||||
type: string
|
||||
description: "OVH API endpoint"
|
||||
default: "https://eu.api.ovh.com/1.0"
|
||||
# ── credentials: fill in ONE of the two sets ─────────────────────────
|
||||
#
|
||||
# A service account (OAuth2 client credentials) is what the control panel
|
||||
# offers on accounts where application keys are not available. Filling in
|
||||
# client_id AND client_secret selects it; anything else falls back to the
|
||||
# historical signed scheme below.
|
||||
client_id:
|
||||
type: string
|
||||
description: "Service account: client ID (OAuth2 client credentials)"
|
||||
client_secret:
|
||||
type: string
|
||||
description: "Service account: client secret"
|
||||
x-soar-sensitive: true
|
||||
oauth_token_url:
|
||||
type: string
|
||||
description: "Service account: token endpoint, only if it differs from the region default (EU: https://www.ovh.com/auth/oauth2/token)"
|
||||
application_key:
|
||||
type: string
|
||||
description: "Application key"
|
||||
description: "Historical scheme: application key"
|
||||
application_secret:
|
||||
type: string
|
||||
description: "Application secret"
|
||||
description: "Historical scheme: application secret"
|
||||
x-soar-sensitive: true
|
||||
consumer_key:
|
||||
type: string
|
||||
description: "Consumer key"
|
||||
description: "Historical scheme: consumer key"
|
||||
x-soar-sensitive: true
|
||||
# ── VoIP on-call routing ─────────────────────────────────────────────
|
||||
#
|
||||
@@ -37,10 +53,12 @@ config_schema:
|
||||
telephony_queue_id:
|
||||
type: string
|
||||
description: "Queue id, only needed when the service holds more than one queue"
|
||||
required:
|
||||
- application_key
|
||||
- application_secret
|
||||
- consumer_key
|
||||
# NOTHING IS REQUIRED HERE, and that is not laxity: this schema cannot express
|
||||
# "one set or the other", and marking the historical three required would refuse
|
||||
# every service-account instance. The scripts refuse an instance with neither,
|
||||
# naming both sets — an error an operator can act on, where a form that will not
|
||||
# submit is one they can only fight.
|
||||
required: []
|
||||
|
||||
commands:
|
||||
- id: get_account
|
||||
|
||||
Reference in New Issue
Block a user