def _validate_shared_secret(self, requestor_id, signature, requestor_address): expected_signature = hmac.new( CONF.neutron.metadata_proxy_shared_secret, requestor_id, hashlib.sha256).hexdigest() if not utils.constant_time_compare(expected_signature, signature): if requestor_id: LOG.warning(_LW('X-Instance-ID-Signature: %(signature)s does ' 'not match the expected value: ' '%(expected_signature)s for id: ' '%(requestor_id)s. Request From: ' '%(requestor_address)s'), {'signature': signature, 'expected_signature': expected_signature, 'requestor_id': requestor_id, 'requestor_address': requestor_address}) msg = _('Invalid proxy request signature.') raise webob.exc.HTTPForbidden(explanation=msg)
def test_constant_time_compare(self): self.assertTrue(utils.constant_time_compare("abcd1234", "abcd1234")) self.assertFalse(utils.constant_time_compare("abcd1234", "a")) self.assertFalse(utils.constant_time_compare("abcd1234", "ABCD234"))
def _handle_instance_id_request(self, req): instance_id = req.headers.get('X-Instance-ID') tenant_id = req.headers.get('X-Tenant-ID') signature = req.headers.get('X-Instance-ID-Signature') remote_address = req.headers.get('X-Forwarded-For') # Ensure that only one header was passed if instance_id is None: msg = _('X-Instance-ID header is missing from request.') elif signature is None: msg = _('X-Instance-ID-Signature header is missing from request.') elif tenant_id is None: msg = _('X-Tenant-ID header is missing from request.') elif not isinstance(instance_id, six.string_types): msg = _('Multiple X-Instance-ID headers found within request.') elif not isinstance(tenant_id, six.string_types): msg = _('Multiple X-Tenant-ID headers found within request.') else: msg = None if msg: raise webob.exc.HTTPBadRequest(explanation=msg) expected_signature = hmac.new( CONF.neutron.metadata_proxy_shared_secret, instance_id, hashlib.sha256).hexdigest() if not utils.constant_time_compare(expected_signature, signature): if instance_id: LOG.warning(_LW('X-Instance-ID-Signature: %(signature)s does ' 'not match the expected value: ' '%(expected_signature)s for id: ' '%(instance_id)s. Request From: ' '%(remote_address)s'), {'signature': signature, 'expected_signature': expected_signature, 'instance_id': instance_id, 'remote_address': remote_address}) msg = _('Invalid proxy request signature.') raise webob.exc.HTTPForbidden(explanation=msg) try: meta_data = self.get_metadata_by_instance_id(instance_id, remote_address) except Exception: LOG.exception(_LE('Failed to get metadata for instance id: %s'), instance_id) msg = _('An unknown error has occurred. ' 'Please try your request again.') raise webob.exc.HTTPInternalServerError( explanation=six.text_type(msg)) if meta_data is None: LOG.error(_LE('Failed to get metadata for instance id: %s'), instance_id) elif meta_data.instance.project_id != tenant_id: LOG.warning(_LW("Tenant_id %(tenant_id)s does not match tenant_id " "of instance %(instance_id)s."), {'tenant_id': tenant_id, 'instance_id': instance_id}) # causes a 404 to be raised meta_data = None return meta_data
def _handle_instance_id_request(self, req): instance_id = req.headers.get('X-Instance-ID') tenant_id = req.headers.get('X-Tenant-ID') signature = req.headers.get('X-Instance-ID-Signature') remote_address = req.headers.get('X-Forwarded-For') # Ensure that only one header was passed if instance_id is None: msg = _('X-Instance-ID header is missing from request.') elif tenant_id is None: msg = _('X-Tenant-ID header is missing from request.') elif not isinstance(instance_id, six.string_types): msg = _('Multiple X-Instance-ID headers found within request.') elif not isinstance(tenant_id, six.string_types): msg = _('Multiple X-Tenant-ID headers found within request.') else: msg = None if msg: raise webob.exc.HTTPBadRequest(explanation=msg) expected_signature = hmac.new( CONF.neutron.metadata_proxy_shared_secret, instance_id, hashlib.sha256).hexdigest() if not utils.constant_time_compare(expected_signature, signature): if instance_id: LOG.warn( _LW('X-Instance-ID-Signature: %(signature)s does ' 'not match the expected value: ' '%(expected_signature)s for id: %(instance_id)s.' ' Request From: %(remote_address)s'), { 'signature': signature, 'expected_signature': expected_signature, 'instance_id': instance_id, 'remote_address': remote_address }) msg = _('Invalid proxy request signature.') raise webob.exc.HTTPForbidden(explanation=msg) try: meta_data = self.get_metadata_by_instance_id( instance_id, remote_address) except Exception: LOG.exception(_('Failed to get metadata for instance id: %s'), instance_id) msg = _('An unknown error has occurred. ' 'Please try your request again.') raise webob.exc.HTTPInternalServerError( explanation=six.text_type(msg)) if meta_data is None: LOG.error(_LE('Failed to get metadata for instance id: %s'), instance_id) elif meta_data.instance['project_id'] != tenant_id: LOG.warn( _LW("Tenant_id %(tenant_id)s does not match tenant_id " "of instance %(instance_id)s."), { 'tenant_id': tenant_id, 'instance_id': instance_id }) # causes a 404 to be raised meta_data = None return meta_data