7
from .base import Provider as BaseProvider
9
LOGGER = logging.getLogger(__name__)
12
'ovh-eu': 'https://eu.api.ovh.com/1.0',
13
'ovh-ca': 'https://ca.api.ovh.com/1.0',
14
'kimsufi-eu': 'https://eu.api.kimsufi.com/1.0',
15
'kimsufi-ca': 'https://ca.api.kimsufi.com/1.0',
16
'soyoustart-eu': 'https://eu.api.soyoustart.com/1.0',
17
'soyoustart-ca': 'https://ca.api.soyoustart.com/1.0',
20
def ProviderParser(subparser):
21
subparser.description = '''
22
OVH Provider requires a token with full rights on /domain/*.
23
It can be generated for your OVH account on the following URL:
24
https://api.ovh.com/createToken/index.cgi?GET=/domain/*&PUT=/domain/*&POST=/domain/*&DELETE=/domain/*'''
25
subparser.add_argument('--auth-entrypoint', help='specify the OVH entrypoint', choices=[
26
'ovh-eu', 'ovh-ca', 'soyoustart-eu', 'soyoustart-ca', 'kimsufi-eu', 'kimsufi-ca'
28
subparser.add_argument('--auth-application-key', help='specify the application key')
29
subparser.add_argument('--auth-application-secret', help='specify the application secret')
30
subparser.add_argument('--auth-consumer-key', help='specify the consumer key')
32
class Provider(BaseProvider):
34
def __init__(self, options, engine_overrides=None):
35
super(Provider, self).__init__(options, engine_overrides)
37
# Handling missing required parameters
38
if not self.options.get('auth_entrypoint'):
39
raise Exception('Error, entrypoint is not defined')
40
if not self.options.get('auth_application_key'):
41
raise Exception('Error, application key is not defined')
42
if not self.options.get('auth_application_secret'):
43
raise Exception('Error, application secret is not defined')
44
if not self.options.get('auth_consumer_key'):
45
raise Exception('Error, consumer key is not defined')
47
# Construct DNS OVH environment
49
self.endpoint_api = ENDPOINTS.get(self.options.get('auth_entrypoint'))
51
# All requests will be done in one HTTPS session
52
self.session = requests.Session()
54
# Calculate delta time between local and OVH to avoid requests rejection
55
server_time = self.session.get('{0}/auth/time'.format(self.endpoint_api)).json()
56
self.time_delta = server_time - int(time.time())
58
def authenticate(self):
59
domain = self.options.get('domain')
61
domains = self._get('/domain/zone/')
62
if domain not in domains:
63
raise Exception('Domain {0} not found'.format(domain))
65
status = self._get('/domain/zone/{0}/status'.format(domain))
66
if not status['isDeployed']:
67
raise Exception('Zone {0} is not deployed'.format(domain))
69
self.domain_id = domain
71
def create_record(self, type, name, content):
72
domain = self.options.get('domain')
73
ttl = self.options.get('ttl')
77
'subDomain': self._relative_name(name),
84
result = self._post('/domain/zone/{0}/record'.format(domain), data)
85
self._post('/domain/zone/{0}/refresh'.format(domain))
87
LOGGER.debug('create_record: %s', result['id'])
91
def list_records(self, type=None, name=None, content=None):
92
domain = self.options.get('domain')
97
params['fieldType'] = type
99
params['subDomain'] = self._relative_name(name)
101
record_ids = self._get('/domain/zone/{0}/record'.format(domain), params)
103
for record_id in record_ids:
104
raw = self._get('/domain/zone/{0}/record/{1}'.format(domain, record_id))
106
'type': raw['fieldType'],
107
'name': self._full_name(raw['subDomain']),
109
'content': raw['target'],
114
records = [record for record in records if record['content'].lower() == content.lower()]
116
LOGGER.debug('list_records: %s', records)
120
def update_record(self, identifier, type=None, name=None, content=None):
121
domain = self.options.get('domain')
124
records = self.list_records(type, name)
125
if len(records) == 1:
126
identifier = records[0]['id']
127
elif len(records) > 1:
128
raise Exception('Several record identifiers match the request')
130
raise Exception('Record identifier could not be found')
134
data['subDomain'] = self._relative_name(name)
136
data['target'] = content
138
self._put('/domain/zone/{0}/record/{1}'.format(domain, identifier), data)
139
self._post('/domain/zone/{0}/refresh'.format(domain))
141
LOGGER.debug('update_record: %s', identifier)
145
def delete_record(self, identifier=None, type=None, name=None, content=None):
146
domain = self.options.get('domain')
149
records = self.list_records(type, name, content)
150
if len(records) == 1:
151
identifier = records[0]['id']
152
elif len(records) > 1:
153
raise Exception('Several record identifiers match the request')
155
raise Exception('Record identifier could not be found')
157
self._delete('/domain/zone/{0}/record/{1}'.format(domain, identifier))
158
self._post('/domain/zone/{0}/refresh'.format(domain))
160
LOGGER.debug('delete_record: %s', identifier)
164
def _request(self, action='GET', url='/', data=None, query_params=None):
166
target = self.endpoint_api + url
170
headers['Content-type'] = 'application/json'
171
body = json.dumps(data)
173
# Get correctly sync time
174
now = str(int(time.time()) + self.time_delta)
176
headers['X-Ovh-Application'] = self.options.get('auth_application_key')
177
headers['X-Ovh-Consumer'] = self.options.get('auth_consumer_key')
178
headers['X-Ovh-Timestamp'] = now
180
request = requests.Request(action, target, data=body, params=query_params, headers=headers)
181
prepared_request = self.session.prepare_request(request)
183
# Build OVH API signature for the current request
184
signature = hashlib.sha1()
185
signature.update('+'.join([
186
self.options.get('auth_application_secret'),
187
self.options.get('auth_consumer_key'),
189
prepared_request.url,
195
prepared_request.headers['X-Ovh-Signature'] = '$1$' + signature.hexdigest()
197
result = self.session.send(prepared_request)
198
result.raise_for_status()