├── examples ├── simpleusage.lua ├── consumerkey.lua └── listauthorized.lua ├── rockspecs └── ovh-api-1.0.0-0.rockspec ├── LICENSE ├── ovh.lua └── README.rst /examples/simpleusage.lua: -------------------------------------------------------------------------------- 1 | local OVH = require 'ovh-api' 2 | 3 | local client = OVH.client( 4 | 'ovh-eu', 5 | 'API_KEY', 6 | 'SECRET_KEY', 7 | 'CONSUMER_KEY' 8 | ) 9 | 10 | -- Print nice welcome message 11 | print('Welcome '..client:get('/me')['firstname']) 12 | -------------------------------------------------------------------------------- /examples/consumerkey.lua: -------------------------------------------------------------------------------- 1 | local OVH = require 'ovh-api' 2 | 3 | local client = OVH.client( 4 | 'ovh-eu', 5 | 'API_KEY', 6 | 'SECRET_KEY', 7 | ) 8 | 9 | local data = client:request_consumerkey({ 10 | { method = 'GET', path = '/*'}, 11 | { method = 'POST', path = '/*'}, 12 | { method = 'PUT', path = '/*'} 13 | }) 14 | 15 | print('Your consumer key is: '..data.consumerKey..'\n') 16 | print('Visit '..data.validationUrl..' to validate the consumer key\n') 17 | print('Press enter when validated\n') 18 | io.read() 19 | print('Welcome '..client:get('/me')['firstname']) 20 | -------------------------------------------------------------------------------- /rockspecs/ovh-api-1.0.0-0.rockspec: -------------------------------------------------------------------------------- 1 | package = "ovh-api" 2 | version = "1.0.0-0" 3 | source = { 4 | url = "git://github.com/yagop/lua-ovh-api", 5 | tag = "v1.0.0" 6 | } 7 | description = { 8 | summary = " Lightweight wrapper for OVH APIs.", 9 | detailed = [[ 10 | Simple lua wrapper over the OVH REST API. 11 | It handles requesting credential, signing queries... 12 | - To get your API keys: https://eu.api.ovh.com/createApp/ 13 | - To get started with API: https://api.ovh.com/g934.first_step_with_api 14 | ]], 15 | homepage = "https://github.com/yagop/lua-ovh-api", 16 | license = "MIT/X11", 17 | maintainer = "Yago Pérez " 18 | } 19 | dependencies = { 20 | "luacrypto", 21 | "luasocket", 22 | "luasec", 23 | "dkjson" 24 | } 25 | build = { 26 | type = "builtin", 27 | modules = { 28 | ["ovh-api"] = "ovh.lua" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Yago 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /examples/listauthorized.lua: -------------------------------------------------------------------------------- 1 | local OVH = require 'ovh-api' 2 | 3 | -- Get configuration from environment variables 4 | local END_POINT = os.getenv("OVH_END_POINT") 5 | local API_KEY = os.getenv("OVH_API_KEY") 6 | local SECRET_KEY = os.getenv("OVH_SECRET_KEY") 7 | local CONSUMER_KEY = os.getenv("OVH_CONSUMER_KEY") 8 | 9 | local client = OVH.client( 10 | END_POINT, 11 | API_KEY, 12 | SECRET_KEY, 13 | CONSUMER_KEY 14 | ) 15 | 16 | local credentials = client:get('/me/api/credential', {status='validated'}) 17 | 18 | local text = 'List of validated credentials: \n' 19 | for _, credentialId in pairs(credentials) do 20 | local url = '/me/api/credential/'..credentialId 21 | credential_data = client:get(url) 22 | credentail_app = client:get(url..'/application') 23 | 24 | local expiration = credential_data.expiration or '' 25 | local lastUse = credential_data.expiration or '' 26 | text = text..'Credential ID: '..credentialId..'\n' 27 | ..'Name: '..credentail_app.name..'\n' 28 | ..'Description: '..credentail_app.description..'\n' 29 | ..'Status: '..credentail_app.status..'\n' 30 | ..'Creation: '..credential_data.creation..'\n' 31 | ..'Expiration: '..expiration..'\n' 32 | ..'Last Use: '..lastUse..'\n\n' 33 | end 34 | 35 | print(text) 36 | -------------------------------------------------------------------------------- /ovh.lua: -------------------------------------------------------------------------------- 1 | local https = require 'ssl.https' 2 | local URL = require 'socket.url' 3 | local crypto = require 'crypto' 4 | local json = require 'dkjson' 5 | local ltn12 = require 'ltn12' 6 | 7 | local Ovh = { 8 | _VERSION = 'ovh-api v1.0.0', 9 | _DESCRIPTION = [[ 10 | Simple lua wrapper over the OVH REST API. 11 | It handles requesting credential, signing queries... 12 | - To get your API keys: https://eu.api.ovh.com/createApp/ 13 | - To get started with API: https://api.ovh.com/g934.first_step_with_api 14 | ]], 15 | _URL = 'https://github.com/yagop/lua-ovh-api', 16 | _LICENSE = [[ 17 | MIT LICENSE 18 | 19 | Copyright (c) 2015 Yago Pérez Sáiz 20 | 21 | Permission is hereby granted, free of charge, to any person obtaining a 22 | copy of this software and associated documentation files (the 23 | "Software"), to deal in the Software without restriction, including 24 | without limitation the rights to use, copy, modify, merge, publish, 25 | distribute, sublicense, and/or sell copies of the Software, and to 26 | permit persons to whom the Software is furnished to do so, subject to 27 | the following conditions: 28 | 29 | The above copyright notice and this permission notice shall be included 30 | in all copies or substantial portions of the Software. 31 | 32 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 33 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 34 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 35 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 36 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 37 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 38 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 39 | ]] 40 | } 41 | 42 | Ovh.__index = Ovh 43 | 44 | local ENDPOINTS = { 45 | ['ovh-eu'] = 'https://eu.api.ovh.com/1.0', 46 | ['ovh-ca'] = 'https://ca.api.ovh.com/1.0', 47 | ['kimsufi-eu'] = 'https://eu.api.kimsufi.com/1.0', 48 | ['kimsufi-ca'] = 'https://ca.api.kimsufi.com/1.0', 49 | ['soyoustart-eu'] = 'https://eu.api.soyoustart.com/1.0', 50 | ['soyoustart-ca'] = 'https://ca.api.soyoustart.com/1.0', 51 | ['runabove-ca'] = 'https://api.runabove.com/1.0' 52 | } 53 | 54 | -- Get the api consumer key 55 | function Ovh:request_consumerkey(accessRules) 56 | -- By default read only 57 | accessRules = accessRules or { 58 | [1] = { method = 'GET', path = '/*'} 59 | } 60 | local reqbody = json.encode({ 61 | accessRules = accessRules 62 | }) 63 | local headers = { 64 | ['X-Ovh-Application'] = self.api_key, 65 | ['content-type'] = 'application/json', 66 | ["content-length"] = tostring(#reqbody) 67 | } 68 | local respbody = {} 69 | local a,code = https.request{ 70 | url = self.api_base..'/auth/credential', 71 | headers = headers, 72 | method = 'POST', 73 | source = ltn12.source.string(reqbody), 74 | sink = ltn12.sink.table(respbody) 75 | } 76 | respbody = table.concat(respbody) 77 | local data = json.decode(respbody) 78 | 79 | if code >= 100 and code < 300 then 80 | self.consumer_key = data.consumerKey 81 | return data 82 | else 83 | if data.message then 84 | error(data.message) 85 | else 86 | error(code) 87 | end 88 | end 89 | end 90 | 91 | function Ovh.client(end_point, api_key, secret_key, consumer_key) 92 | local api_base = ENDPOINTS[end_point] 93 | -- Default end point 94 | api_base = api_base or ENDPOINTS['ovh-eu'] 95 | local self = setmetatable({ 96 | api_base = api_base, 97 | api_key = api_key, 98 | secret_key = secret_key, 99 | consumer_key = consumer_key 100 | }, Ovh) 101 | return self 102 | end 103 | 104 | function Ovh:auth_request(method, path, query, body) 105 | -- "$1$" + SHA1_HEX(AS+"+"+CK+"+"+METHOD+"+"+QUERY+"+"+BODY+"+"+TSTAMP) 106 | local url = self.api_base..path 107 | if query then 108 | url = url..'?' 109 | for key, val in pairs(query) do 110 | key = URL.escape(key) 111 | val = URL.escape(val) 112 | url = url..key..'='..val..'&' 113 | end 114 | end 115 | local body = body or '' 116 | local timestamp = os.time() 117 | local text = table.concat({ self.secret_key, 118 | self.consumer_key, 119 | method, 120 | url, 121 | body, 122 | timestamp},'+') 123 | 124 | local sign = '$1$'..crypto.digest('sha1', text, false) 125 | 126 | local headers = { 127 | ['Content-type'] = 'application/json', 128 | ["content-length"] = tostring(#body), 129 | ['X-Ovh-Timestamp'] = timestamp, 130 | ['X-Ovh-Signature'] = sign, 131 | ['X-Ovh-Consumer'] = self.consumer_key, 132 | ['X-Ovh-Application'] = self.api_key 133 | } 134 | 135 | local respbody = {} 136 | local a,code = https.request{ 137 | url = url, 138 | sink = ltn12.sink.table(respbody), 139 | headers = headers, 140 | method = method, 141 | source = ltn12.source.string(body) 142 | } 143 | respbody = table.concat(respbody) 144 | local data = json.decode(respbody) 145 | 146 | if code >= 100 and code < 300 then 147 | return data 148 | else 149 | if data.message then 150 | error(data.message) 151 | else 152 | error(code) 153 | end 154 | end 155 | end 156 | 157 | function Ovh:get(path, query) 158 | return self:auth_request('GET', path, query) 159 | end 160 | 161 | function Ovh:put(path, data) 162 | return self:auth_request('PUT', path, nil, data) 163 | end 164 | 165 | function Ovh:post(path, data) 166 | return self:auth_request('POST', path, nil, data) 167 | end 168 | 169 | function Ovh:delete(path, data) 170 | return self:auth_request('DELETE', path, nil, data) 171 | end 172 | 173 | return Ovh 174 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | Lightweight wrapper around OVH's APIs. Handles all the hard work including 2 | credential creation and requests signing. 3 | 4 | .. code:: lua 5 | 6 | local OVH = require 'ovh-api' 7 | 8 | local client = OVH.client( 9 | "ovh-eu", 10 | "API_KEY", 11 | "SECRET_KEY", 12 | "CONSUMER_KEY" 13 | ) 14 | 15 | -- Print nice welcome message 16 | print("Welcome"..client:get('/me')['firstname']) 17 | 18 | Installation 19 | ============ 20 | 21 | The easiest way to get the latest stable release is to grab it from ```luarocks``. 22 | 23 | .. code:: bash 24 | 25 | luarocks install ovh-api 26 | 27 | Example Usage 28 | ============= 29 | 30 | Use the API on behalf of a user 31 | ------------------------------- 32 | 33 | 1. Create an application 34 | ************************ 35 | 36 | To interact with the APIs, the SDK needs to identify itself using an 37 | ``application_key`` and an ``application_secret``. To get them, you need 38 | to register your application. Depending the API you plan yo use, visit: 39 | 40 | - `OVH Europe `_ 41 | - `OVH North-America `_ 42 | - `So you Start Europe `_ 43 | - `So you Start North America `_ 44 | - `Kimsufi Europe `_ 45 | - `Kimsufi North America `_ 46 | - `RunAbove `_ 47 | 48 | Once created, you will obtain an **application key (AK)** and an **application 49 | secret (AS)**. 50 | 51 | 2. Authorize your application to access a customer account 52 | ********************************************************** 53 | 54 | To allow your application to access a customer account using the API on your 55 | behalf, you need a **consumer key (CK)**. 56 | 57 | Here is a sample code you can use to allow your application to access a 58 | customer's informations: 59 | 60 | .. code:: lua 61 | 62 | local OVH = require 'ovh-api' 63 | 64 | local client = OVH.client( 65 | 'ovh-eu', 66 | 'API_KEY', 67 | 'SECRET_KEY', 68 | ) 69 | 70 | local data = client:request_consumerkey({ 71 | { method = 'GET', path = '/*'}, 72 | { method = 'POST', path = '/*'}, 73 | { method = 'PUT', path = '/*'} 74 | }) 75 | 76 | print('Your consumer key is: '..data.consumerKey..'\n') 77 | print('Visit '..data.validationUrl..' to validate the consumer key\n') 78 | print('Press enter when validated\n') 79 | io.read() 80 | print('Welcome '..client:get('/me')['firstname']) 81 | 82 | 83 | Returned ``consumerKey`` should then be kept to avoid re-authenticating your 84 | end-user on each use. 85 | 86 | .. note:: To request full and unlimited access to the API, you may use wildcards: 87 | 88 | .. code:: lua 89 | 90 | client:request_consumerkey({ 91 | { method = 'GET', path = '/*'}, 92 | { method = 'POST', path = '/*'}, 93 | { method = 'PUT', path = '/*'}, 94 | { method = 'DELETE', path = '/*'} 95 | }) 96 | 97 | List application authorized to access your account 98 | -------------------------------------------------- 99 | 100 | Thanks to the application key / consumer key mechanism, it is possible to 101 | finely track applications having access to your data and revoke this access. 102 | This examples lists validated applications. It could easily be adapted to 103 | manage revocation too. 104 | 105 | This example assumes an existing Configuration_ with valid ``API_KEY``, 106 | ``SECRET_KEY`` and ``CONSUMER_KEY``. 107 | 108 | .. code:: lua 109 | 110 | local OVH = require '../ovh' 111 | 112 | -- Get configuration from environment variables 113 | local END_POINT = os.getenv("OVH_END_POINT") 114 | local API_KEY = os.getenv("OVH_API_KEY") 115 | local SECRET_KEY = os.getenv("OVH_SECRET_KEY") 116 | local CONSUMER_KEY = os.getenv("OVH_CONSUMER_KEY") 117 | 118 | local client = OVH.client( 119 | END_POINT, 120 | API_KEY, 121 | SECRET_KEY, 122 | CONSUMER_KEY 123 | ) 124 | 125 | local credentials = client:get('/me/api/credential', {status='validated'}) 126 | 127 | local text = 'List of validated credentials: \n' 128 | for _, credentialId in pairs(credentials) do 129 | local url = '/me/api/credential/'..credentialId 130 | credential_data = client:get(url) 131 | credentail_app = client:get(url..'/application') 132 | 133 | local expiration = credential_data.expiration or '' 134 | local lastUse = credential_data.expiration or '' 135 | text = text..'Credential ID: '..credentialId..'\n' 136 | ..'Name: '..credentail_app.name..'\n' 137 | ..'Description: '..credentail_app.description..'\n' 138 | ..'Status: '..credentail_app.status..'\n' 139 | ..'Creation: '..credential_data.creation..'\n' 140 | ..'Expiration: '..expiration..'\n' 141 | ..'Last Use: '..lastUse..'\n\n' 142 | end 143 | 144 | print(text) 145 | 146 | Supported APIs 147 | ============== 148 | 149 | OVH Europe 150 | ---------- 151 | 152 | - **Documentation**: https://eu.api.ovh.com/ 153 | - **Community support**: api-subscribe@ml.ovh.net 154 | - **Console**: https://eu.api.ovh.com/console 155 | - **Create application credentials**: https://eu.api.ovh.com/createApp/ 156 | - **Create script credentials** (all keys at once): https://eu.api.ovh.com/createToken/ 157 | 158 | OVH North America 159 | ----------------- 160 | 161 | - **Documentation**: https://ca.api.ovh.com/ 162 | - **Community support**: api-subscribe@ml.ovh.net 163 | - **Console**: https://ca.api.ovh.com/console 164 | - **Create application credentials**: https://ca.api.ovh.com/createApp/ 165 | - **Create script credentials** (all keys at once): https://ca.api.ovh.com/createToken/ 166 | 167 | So you Start Europe 168 | ------------------- 169 | 170 | - **Documentation**: https://eu.api.soyoustart.com/ 171 | - **Community support**: api-subscribe@ml.ovh.net 172 | - **Console**: https://eu.api.soyoustart.com/console/ 173 | - **Create application credentials**: https://eu.api.soyoustart.com/createApp/ 174 | - **Create script credentials** (all keys at once): https://eu.api.soyoustart.com/createToken/ 175 | 176 | So you Start North America 177 | -------------------------- 178 | 179 | - **Documentation**: https://ca.api.soyoustart.com/ 180 | - **Community support**: api-subscribe@ml.ovh.net 181 | - **Console**: https://ca.api.soyoustart.com/console/ 182 | - **Create application credentials**: https://ca.api.soyoustart.com/createApp/ 183 | - **Create script credentials** (all keys at once): https://ca.api.soyoustart.com/createToken/ 184 | 185 | Kimsufi Europe 186 | -------------- 187 | 188 | - **Documentation**: https://eu.api.kimsufi.com/ 189 | - **Community support**: api-subscribe@ml.ovh.net 190 | - **Console**: https://eu.api.kimsufi.com/console/ 191 | - **Create application credentials**: https://eu.api.kimsufi.com/createApp/ 192 | - **Create script credentials** (all keys at once): https://eu.api.kimsufi.com/createToken/ 193 | 194 | Kimsufi North America 195 | --------------------- 196 | 197 | - **Documentation**: https://ca.api.kimsufi.com/ 198 | - **Community support**: api-subscribe@ml.ovh.net 199 | - **Console**: https://ca.api.kimsufi.com/console/ 200 | - **Create application credentials**: https://ca.api.kimsufi.com/createApp/ 201 | - **Create script credentials** (all keys at once): https://ca.api.kimsufi.com/createToken/ 202 | 203 | Runabove 204 | -------- 205 | 206 | - **Community support**: https://community.runabove.com/ 207 | - **Console**: https://api.runabove.com/console/ 208 | - **Create application credentials**: https://api.runabove.com/createApp/ 209 | - **High level SDK**: https://github.com/runabove/python-runabove 210 | --------------------------------------------------------------------------------