Add method to wrap HashiCorp Vault HTTP API calls.
The new method handles the HTTP request for the Vault HTTP API
and does the error checking in a single place. The same code
was already in four different places in the same file.
Change-Id: I4b688d8cf994fb26f88570840523fcc0ac24faba
Signed-off-by: Moises Guimaraes de Medeiros <moguimar@redhat.com>
Moises Guimaraes de Medeiros
4 years ago
103 | 103 | if self._vault_kv_version: |
104 | 104 | return self._vault_kv_version |
105 | 105 | |
106 | resource_url = self._get_url() + 'v1/sys/internal/ui/mounts/secret' | |
107 | resp = self._do_http_request(self._session.get, resource_url) | |
108 | ||
109 | if resp.status_code == requests.codes['not_found']: | |
110 | self._vault_kv_version = '1' | |
111 | else: | |
112 | self._vault_kv_version = resp.json()['data']['options']['version'] | |
113 | ||
114 | return self._vault_kv_version | |
115 | ||
116 | def _get_resource_url(self, key_id=None): | |
117 | return '{}v1/secret/{}{}'.format( | |
118 | self._get_url(), | |
119 | ||
120 | '' if self._get_api_version() == '1' else | |
121 | 'data/' if key_id else | |
122 | 'metadata/', # no key_id is for listing and 'data/' doesn't works | |
123 | ||
124 | key_id if key_id else '?list=true') | |
125 | ||
126 | def _do_http_request(self, method, resource, json=None): | |
127 | verify = self._verify_server | |
106 | 128 | headers = {'X-Vault-Token': self._root_token_id} |
129 | ||
107 | 130 | try: |
108 | resource_url = self._get_url() + 'v1/sys/internal/ui/mounts/secret' | |
109 | resp = self._session.get(resource_url, | |
110 | verify=self._verify_server, | |
111 | headers=headers) | |
131 | resp = method(resource, headers=headers, json=json, verify=verify) | |
112 | 132 | except requests.exceptions.Timeout as ex: |
113 | 133 | raise exception.KeyManagerError(six.text_type(ex)) |
114 | 134 | except requests.exceptions.ConnectionError as ex: |
120 | 140 | raise exception.KeyManagerError(resp.reason) |
121 | 141 | if resp.status_code == requests.codes['forbidden']: |
122 | 142 | raise exception.Forbidden() |
123 | if resp.status_code == requests.codes['not_found']: | |
124 | self._vault_kv_version = '1' | |
125 | else: | |
126 | self._vault_kv_version = resp.json()['data']['options']['version'] | |
127 | ||
128 | return self._vault_kv_version | |
143 | ||
144 | return resp | |
129 | 145 | |
130 | 146 | def create_key_pair(self, context, algorithm, length, |
131 | 147 | expiration=None, name=None): |
185 | 201 | raise exception.KeyManagerError( |
186 | 202 | "Unknown type for value : %r" % value) |
187 | 203 | |
188 | headers = {'X-Vault-Token': self._root_token_id} | |
189 | try: | |
190 | resource_url = '{}v1/secret/{}{}'.format( | |
191 | self._get_url(), | |
192 | '' if self._get_api_version() == '1' else 'data/', | |
193 | key_id) | |
194 | ||
195 | record = { | |
196 | 'type': type_value, | |
197 | 'value': binascii.hexlify(value.get_encoded()).decode('utf-8'), | |
198 | 'algorithm': (value.algorithm if hasattr(value, 'algorithm') | |
199 | else None), | |
200 | 'bit_length': (value.bit_length if hasattr(value, 'bit_length') | |
201 | else None), | |
202 | 'name': value.name, | |
203 | 'created': value.created | |
204 | } | |
205 | if self._get_api_version() != '1': | |
206 | record = {'data': record} | |
207 | ||
208 | resp = self._session.post(resource_url, | |
209 | verify=self._verify_server, | |
210 | json=record, | |
211 | headers=headers) | |
212 | except requests.exceptions.Timeout as ex: | |
213 | raise exception.KeyManagerError(six.text_type(ex)) | |
214 | except requests.exceptions.ConnectionError as ex: | |
215 | raise exception.KeyManagerError(six.text_type(ex)) | |
216 | except Exception as ex: | |
217 | raise exception.KeyManagerError(six.text_type(ex)) | |
218 | ||
219 | if resp.status_code in _EXCEPTIONS_BY_CODE: | |
220 | raise exception.KeyManagerError(resp.reason) | |
221 | if resp.status_code == requests.codes['forbidden']: | |
222 | raise exception.Forbidden() | |
204 | record = { | |
205 | 'type': type_value, | |
206 | 'value': binascii.hexlify(value.get_encoded()).decode('utf-8'), | |
207 | 'algorithm': (value.algorithm if hasattr(value, 'algorithm') | |
208 | else None), | |
209 | 'bit_length': (value.bit_length if hasattr(value, 'bit_length') | |
210 | else None), | |
211 | 'name': value.name, | |
212 | 'created': value.created | |
213 | } | |
214 | if self._get_api_version() != '1': | |
215 | record = {'data': record} | |
216 | ||
217 | self._do_http_request(self._session.post, | |
218 | self._get_resource_url(key_id), | |
219 | json=record) | |
223 | 220 | |
224 | 221 | return key_id |
225 | 222 | |
262 | 259 | if not key_id: |
263 | 260 | raise exception.KeyManagerError('key identifier not provided') |
264 | 261 | |
265 | headers = {'X-Vault-Token': self._root_token_id} | |
266 | try: | |
267 | resource_url = '{}v1/secret/{}{}'.format( | |
268 | self._get_url(), | |
269 | '' if self._get_api_version() == '1' else 'data/', | |
270 | key_id) | |
271 | ||
272 | resp = self._session.get(resource_url, | |
273 | verify=self._verify_server, | |
274 | headers=headers) | |
275 | except requests.exceptions.Timeout as ex: | |
276 | raise exception.KeyManagerError(six.text_type(ex)) | |
277 | except requests.exceptions.ConnectionError as ex: | |
278 | raise exception.KeyManagerError(six.text_type(ex)) | |
279 | except Exception as ex: | |
280 | raise exception.KeyManagerError(six.text_type(ex)) | |
281 | ||
282 | if resp.status_code in _EXCEPTIONS_BY_CODE: | |
283 | raise exception.KeyManagerError(resp.reason) | |
284 | if resp.status_code == requests.codes['forbidden']: | |
285 | raise exception.Forbidden() | |
262 | resp = self._do_http_request(self._session.get, | |
263 | self._get_resource_url(key_id)) | |
264 | ||
286 | 265 | if resp.status_code == requests.codes['not_found']: |
287 | 266 | raise exception.ManagedObjectNotFoundError(uuid=key_id) |
288 | 267 | |
325 | 304 | if not key_id: |
326 | 305 | raise exception.KeyManagerError('key identifier not provided') |
327 | 306 | |
328 | headers = {'X-Vault-Token': self._root_token_id} | |
329 | try: | |
330 | resource_url = '{}v1/secret/{}{}'.format( | |
331 | self._get_url(), | |
332 | '' if self._get_api_version() == '1' else 'data/', | |
333 | key_id) | |
334 | ||
335 | resp = self._session.delete(resource_url, | |
336 | verify=self._verify_server, | |
337 | headers=headers) | |
338 | except requests.exceptions.Timeout as ex: | |
339 | raise exception.KeyManagerError(six.text_type(ex)) | |
340 | except requests.exceptions.ConnectionError as ex: | |
341 | raise exception.KeyManagerError(six.text_type(ex)) | |
342 | except Exception as ex: | |
343 | raise exception.KeyManagerError(six.text_type(ex)) | |
344 | ||
345 | if resp.status_code in _EXCEPTIONS_BY_CODE: | |
346 | raise exception.KeyManagerError(resp.reason) | |
347 | if resp.status_code == requests.codes['forbidden']: | |
348 | raise exception.Forbidden() | |
307 | resp = self._do_http_request(self._session.delete, | |
308 | self._get_resource_url(key_id)) | |
309 | ||
349 | 310 | if resp.status_code == requests.codes['not_found']: |
350 | 311 | raise exception.ManagedObjectNotFoundError(uuid=key_id) |
351 | 312 | |
361 | 322 | msg = _("Invalid secret type: %s") % object_type |
362 | 323 | raise exception.KeyManagerError(reason=msg) |
363 | 324 | |
364 | headers = {'X-Vault-Token': self._root_token_id} | |
365 | try: | |
366 | resource_url = '{}v1/secret/{}?list=true'.format( | |
367 | self._get_url(), | |
368 | '' if self._get_api_version() == '1' else 'metadata/') | |
369 | ||
370 | resp = self._session.get(resource_url, | |
371 | verify=self._verify_server, | |
372 | headers=headers) | |
373 | keys = resp.json()['data']['keys'] | |
374 | except requests.exceptions.Timeout as ex: | |
375 | raise exception.KeyManagerError(six.text_type(ex)) | |
376 | except requests.exceptions.ConnectionError as ex: | |
377 | raise exception.KeyManagerError(six.text_type(ex)) | |
378 | except Exception as ex: | |
379 | raise exception.KeyManagerError(six.text_type(ex)) | |
380 | ||
381 | if resp.status_code in _EXCEPTIONS_BY_CODE: | |
382 | raise exception.KeyManagerError(resp.reason) | |
383 | if resp.status_code == requests.codes['forbidden']: | |
384 | raise exception.Forbidden() | |
325 | resp = self._do_http_request(self._session.get, | |
326 | self._get_resource_url()) | |
327 | ||
385 | 328 | if resp.status_code == requests.codes['not_found']: |
386 | 329 | keys = [] |
330 | else: | |
331 | keys = resp.json()['data']['keys'] | |
387 | 332 | |
388 | 333 | objects = [] |
389 | 334 | for obj_id in keys: |