Skip to content

Commit dcce58f

Browse files
committed
Initial code for plugin
1 parent 99da9a5 commit dcce58f

File tree

5 files changed

+147
-0
lines changed

5 files changed

+147
-0
lines changed
20.5 KB
Loading
44.5 KB
Loading

README.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# OVH Cloud API Signature for Insomnia
2+
3+
This is a plugin for [Insomnia](https://insomnia.rest/) that generates the `X-Ovh-Signature` signature header for API calls to the [OVH Cloud API](https://docs.ovh.com/gb/en/api/first-steps-with-ovh-api/#first-api-usage).
4+
5+
OVH Cloud API calls require that once you have obtained your three keys (AK, AS, CK), you need to sign all API requests. The signature is calculated as follows:
6+
7+
```
8+
SHA1_HEX(AS+"+"+CK+"+"+METHOD+"+"+QUERY+"+"+BODY+"+"+TSTAMP)
9+
```
10+
11+
## Installation
12+
13+
Install the `insomnia-plugin-ovhcloud-signature` plugin from Preferences -> Plugins.
14+
15+
## How to use
16+
17+
### Setup for OVH API Calls
18+
19+
[Generate your Application Keys](https://docs.ovh.com/gb/en/api/first-steps-with-ovh-api/#advanced-usage-pair-ovhcloud-apis-with-an-application_2). Once you have created the keys, you will be issued three keys:
20+
21+
- The Application Key, called AK
22+
- The Application Secret, _not to be disclosed_, called AS
23+
- The Secret Consumer Key, _not to be disclosed_, called CK
24+
25+
You will need to add your own headers for:
26+
27+
- `X-Ovh-Application` with the value of the Application Key
28+
- `X-Ovh-Consumer` with the value of the Secret Consumer Key
29+
30+
You can template these in a private environment like:
31+
32+
```json
33+
{
34+
"ApplicationKey": "1234567890abcdef",
35+
"ApplicationSecret": "1029384756abcdef",
36+
"ConsumerKey": "0987654321defabc"
37+
}
38+
```
39+
40+
Then using a plugin like the [Global Headers](https://insomnia.rest/plugins/insomnia-plugin-global-headers) you can set your _Base Environment_ to be something like:
41+
42+
```json
43+
{
44+
"basePath": "https://api.ovh.com/1.0",
45+
"GLOBAL_HEADERS": {
46+
"Accept": "application/json",
47+
"Content-Type": "application/json;charset=utf-8",
48+
"X-Ovh-Application": "{{ApplicationKey}}",
49+
"X-Ovh-Consumer": "{{ConsumerKey}}"
50+
}
51+
}
52+
```
53+
54+
### Setup this plugin
55+
56+
Add the `OVH Signature` template tag to a request header.
57+
58+
![request example](./.github/assets/insomnia-add-header.png)
59+
60+
Provide the values manually or from your private environment variables:
61+
62+
![request example](./.github/assets/insomnia-edit-tag.png)
63+
64+
The plugin will generate and add the headers:
65+
66+
- `X-Ovh-Timestamp`
67+
- `X-Ovh-Signature`

package.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "insomnia-plugin-ovhcloud-signature",
3+
"version": "1.0.0",
4+
"license": "BSD-3-Clause",
5+
"author": "Lantrix",
6+
"main": "plugin.js",
7+
"insomnia": {
8+
"name": "ovhCloudSignature",
9+
"displayName": "OVH Cloud Signature Generator",
10+
"description": "Generates the X-Ovh-Signature for OVH Cloud API requests."
11+
},
12+
"dependencies": {
13+
"lodash": "^4.17.21"
14+
},
15+
"devDependencies": {}
16+
}

plugin.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
const crypto = require('crypto')
2+
const lodash = require('lodash')
3+
4+
module.exports.templateTags = [
5+
{
6+
name: 'ovhsignature',
7+
displayName: 'OVH Signature',
8+
description: 'Sign OVH CLoud API requests',
9+
10+
args: [
11+
{
12+
displayName: 'Application Secret Key',
13+
type: 'string',
14+
},
15+
{
16+
displayName: 'Consumer Key',
17+
type: 'string',
18+
},
19+
],
20+
21+
async run(context, as, ck, headers) {
22+
23+
if (!as) throw new Error('missing Application Secret Key')
24+
if (!ck) throw new Error('missing Consumer Key')
25+
26+
await Promise.all([
27+
context.store.setItem("ovhcloud-as", as),
28+
context.store.setItem("ovhcloud-ck", ck),
29+
])
30+
31+
return
32+
},
33+
},
34+
]
35+
36+
function signOvhRequest(as, ck, httpMethod, url, body, timestamp) {
37+
let signed = [ as, ck, httpMethod, url, '', timestamp ];
38+
return '$1$' + crypto.createHash('sha1').update(signed.join('+')).digest('hex');
39+
}
40+
41+
module.exports.requestHooks = [async (context) => {
42+
console.log("Inserting X-Ovh-Signature into http headers")
43+
const as = await context.store.getItem("ovhcloud-as")
44+
console.log("as " + as)
45+
const ck = await context.store.getItem("ovhcloud-ck")
46+
console.log("ck " + ck)
47+
const requestUrl = context.request.getUrl();
48+
console.log("requestUrl " + requestUrl)
49+
const body = context.request.getBody();
50+
let requestBody;
51+
if(lodash.isEmpty(body)) {
52+
requestBody = ""
53+
} else {
54+
requestBody = body
55+
}
56+
console.log("requestBody " + requestBody);
57+
const httpMethod = context.request.getMethod().toUpperCase();
58+
console.log("httpMethod " + httpMethod)
59+
const timestamp = Math.round(Date.now() / 1000)
60+
context.request.setHeader("X-Ovh-Timestamp", timestamp);
61+
const signature = signOvhRequest(as, ck, httpMethod, requestUrl, requestBody, timestamp)
62+
context.request.setHeader("X-Ovh-Signature", signature);
63+
}]
64+

0 commit comments

Comments
 (0)