Merge remote-tracking branch 'mainRepo/master' into task/5509/add-keys-to-opennebula-user
This commit is contained in:
		
				commit
				
					
						6d3b5f40c0
					
				
			
		
					 8 changed files with 88 additions and 6 deletions
				
			
		|  | @ -1,4 +1,8 @@ | ||||||
| Next: | 2.5.11: 2019-06-11 | ||||||
|  |    *  #6672: [api] Check VM belongs to user in the infrastructure directly (MR!707) | ||||||
|  |    *  #bugfix: DE translation fix "Learn mehr" -> "Lerne mehr" (MR!708) | ||||||
|  | 2.5.10: 2019-05-16 | ||||||
|  |    *  #6672: [api] REST endpoint for ungleich-cli to verify if a VM belongs to a user (MR!705) | ||||||
|    *  #6670: [hosting/save_ssh_key] Upgrade cdist version to 5.0.1 to manage keys on Alpine linux |    *  #6670: [hosting/save_ssh_key] Upgrade cdist version to 5.0.1 to manage keys on Alpine linux | ||||||
| 2.5.9: 2019-05-09 | 2.5.9: 2019-05-09 | ||||||
|    *  #6669: [hosting] Fix opennebula vm query takes long (MR!703) |    *  #6669: [hosting] Fix opennebula vm query takes long (MR!703) | ||||||
|  |  | ||||||
|  | @ -1,5 +1,8 @@ | ||||||
| import logging | import logging | ||||||
|  | import pyotp | ||||||
|  | import requests | ||||||
| from django.contrib.sites.models import Site | from django.contrib.sites.models import Site | ||||||
|  | from django.conf import settings | ||||||
| 
 | 
 | ||||||
| from datacenterlight.tasks import create_vm_task | from datacenterlight.tasks import create_vm_task | ||||||
| from hosting.models import HostingOrder, HostingBill, OrderDetail | from hosting.models import HostingOrder, HostingBill, OrderDetail | ||||||
|  | @ -11,7 +14,6 @@ from .models import VMPricing, VMTemplate | ||||||
| 
 | 
 | ||||||
| logger = logging.getLogger(__name__) | logger = logging.getLogger(__name__) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| def get_cms_integration(name): | def get_cms_integration(name): | ||||||
|     current_site = Site.objects.get_current() |     current_site = Site.objects.get_current() | ||||||
|     try: |     try: | ||||||
|  | @ -100,3 +102,22 @@ def clear_all_session_vars(request): | ||||||
|                             'generic_payment_details', 'product_id']: |                             'generic_payment_details', 'product_id']: | ||||||
|             if session_var in request.session: |             if session_var in request.session: | ||||||
|                 del request.session[session_var] |                 del request.session[session_var] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def check_otp(name, realm, token): | ||||||
|  |     data = { | ||||||
|  |         "auth_name": settings.AUTH_NAME, | ||||||
|  |         "auth_token": pyotp.TOTP(settings.AUTH_SEED).now(), | ||||||
|  |         "auth_realm": settings.AUTH_REALM, | ||||||
|  |         "name": name, | ||||||
|  |         "realm": realm, | ||||||
|  |         "token": token | ||||||
|  |     } | ||||||
|  |     response = requests.post( | ||||||
|  |         "https://{OTP_SERVER}{OTP_VERIFY_ENDPOINT}".format( | ||||||
|  |             OTP_SERVER=settings.OTP_SERVER, | ||||||
|  |             OTP_VERIFY_ENDPOINT=settings.OTP_VERIFY_ENDPOINT | ||||||
|  |         ), | ||||||
|  |         data=data | ||||||
|  |     ) | ||||||
|  |     return response.status_code | ||||||
|  |  | ||||||
|  | @ -342,7 +342,7 @@ msgstr "" | ||||||
| "dieser Website erklärst Du Dich damit einverstanden, diese zu nutzen." | "dieser Website erklärst Du Dich damit einverstanden, diese zu nutzen." | ||||||
| 
 | 
 | ||||||
| msgid "Learn more" | msgid "Learn more" | ||||||
| msgstr "Learn mehr" | msgstr "Lerne mehr" | ||||||
| 
 | 
 | ||||||
| msgid "OK" | msgid "OK" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
|  | @ -721,6 +721,14 @@ X_FRAME_OPTIONS = ('SAMEORIGIN' if X_FRAME_OPTIONS_ALLOW_FROM_URI is None else | ||||||
| 
 | 
 | ||||||
| DEBUG = bool_env('DEBUG') | DEBUG = bool_env('DEBUG') | ||||||
| 
 | 
 | ||||||
|  | READ_VM_REALM = env('READ_VM_REALM') | ||||||
|  | AUTH_NAME = env('AUTH_NAME') | ||||||
|  | AUTH_SEED = env('AUTH_SEED') | ||||||
|  | AUTH_REALM = env('AUTH_REALM') | ||||||
|  | OTP_SERVER = env('OTP_SERVER') | ||||||
|  | OTP_VERIFY_ENDPOINT = env('OTP_VERIFY_ENDPOINT') | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| if DEBUG: | if DEBUG: | ||||||
|     from .local import *  # flake8: noqa |     from .local import *  # flake8: noqa | ||||||
| else: | else: | ||||||
|  |  | ||||||
|  | @ -45,7 +45,12 @@ class Command(BaseCommand): | ||||||
|                     num_invoice_created = 0 |                     num_invoice_created = 0 | ||||||
|                     for invoice in all_invoices: |                     for invoice in all_invoices: | ||||||
|                         invoice['customer'] = user.stripecustomer |                         invoice['customer'] = user.stripecustomer | ||||||
|                         num_invoice_created += 1 if MonthlyHostingBill.create(invoice) is not None else logger.error("Did not import invoice for %s" % str(invoice)) |                         try: | ||||||
|  |                             existing_mhb = MonthlyHostingBill.objects.get(invoice_id=invoice['invoice_id']) | ||||||
|  |                             logger.debug("Invoice %s exists already. Not importing." % invoice['invoice_id']) | ||||||
|  |                         except MonthlyHostingBill.DoesNotExist as dne: | ||||||
|  |                             logger.debug("Invoice id %s does not exist" % invoice['invoice_id']) | ||||||
|  |                             num_invoice_created += 1 if MonthlyHostingBill.create(invoice) is not None else logger.error("Did not import invoice for %s" % str(invoice)) | ||||||
|                     self.stdout.write( |                     self.stdout.write( | ||||||
|                         self.style.SUCCESS("Number of invoices imported = %s" % num_invoice_created) |                         self.style.SUCCESS("Number of invoices imported = %s" % num_invoice_created) | ||||||
|                     ) |                     ) | ||||||
|  |  | ||||||
|  | @ -10,12 +10,13 @@ from .views import ( | ||||||
|     HostingPricingView, CreateVirtualMachinesView, HostingBillListView, |     HostingPricingView, CreateVirtualMachinesView, HostingBillListView, | ||||||
|     HostingBillDetailView, SSHKeyDeleteView, SSHKeyCreateView, SSHKeyListView, |     HostingBillDetailView, SSHKeyDeleteView, SSHKeyCreateView, SSHKeyListView, | ||||||
|     SSHKeyChoiceView, DashboardView, SettingsView, ResendActivationEmailView, |     SSHKeyChoiceView, DashboardView, SettingsView, ResendActivationEmailView, | ||||||
|     InvoiceListView, InvoiceDetailView |     InvoiceListView, InvoiceDetailView, CheckUserVM | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| urlpatterns = [ | urlpatterns = [ | ||||||
|     url(r'index/?$', IndexView.as_view(), name='index'), |     url(r'index/?$', IndexView.as_view(), name='index'), | ||||||
|     url(r'django/?$', DjangoHostingView.as_view(), name='djangohosting'), |     url(r'django/?$', DjangoHostingView.as_view(), name='djangohosting'), | ||||||
|  |     url(r'checkvm/?$', CheckUserVM.as_view(), name='check_vm'), | ||||||
|     url(r'dashboard/?$', DashboardView.as_view(), name='dashboard'), |     url(r'dashboard/?$', DashboardView.as_view(), name='dashboard'), | ||||||
|     url(r'nodejs/?$', NodeJSHostingView.as_view(), name='nodejshosting'), |     url(r'nodejs/?$', NodeJSHostingView.as_view(), name='nodejshosting'), | ||||||
|     url(r'rails/?$', RailsHostingView.as_view(), name='railshosting'), |     url(r'rails/?$', RailsHostingView.as_view(), name='railshosting'), | ||||||
|  |  | ||||||
|  | @ -28,13 +28,16 @@ from django.views.generic import ( | ||||||
| ) | ) | ||||||
| from guardian.mixins import PermissionRequiredMixin | from guardian.mixins import PermissionRequiredMixin | ||||||
| from oca.pool import WrongIdError | from oca.pool import WrongIdError | ||||||
|  | from rest_framework.renderers import JSONRenderer | ||||||
|  | from rest_framework.response import Response | ||||||
|  | from rest_framework.views import APIView | ||||||
| from stored_messages.api import mark_read | from stored_messages.api import mark_read | ||||||
| from stored_messages.models import Message | from stored_messages.models import Message | ||||||
| from stored_messages.settings import stored_messages_settings | from stored_messages.settings import stored_messages_settings | ||||||
| 
 | 
 | ||||||
| from datacenterlight.cms_models import DCLCalculatorPluginModel | from datacenterlight.cms_models import DCLCalculatorPluginModel | ||||||
| from datacenterlight.models import VMTemplate, VMPricing | from datacenterlight.models import VMTemplate, VMPricing | ||||||
| from datacenterlight.utils import create_vm, get_cms_integration | from datacenterlight.utils import create_vm, get_cms_integration, check_otp | ||||||
| from hosting.models import UserCardDetail | from hosting.models import UserCardDetail | ||||||
| from membership.models import CustomUser, StripeCustomer | from membership.models import CustomUser, StripeCustomer | ||||||
| from opennebula_api.models import OpenNebulaManager | from opennebula_api.models import OpenNebulaManager | ||||||
|  | @ -67,9 +70,12 @@ from .models import ( | ||||||
| 
 | 
 | ||||||
| logger = logging.getLogger(__name__) | logger = logging.getLogger(__name__) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| CONNECTION_ERROR = "Your VMs cannot be displayed at the moment due to a \ | CONNECTION_ERROR = "Your VMs cannot be displayed at the moment due to a \ | ||||||
|                     backend connection error. please try again in a few \ |                     backend connection error. please try again in a few \ | ||||||
|                     minutes." |                     minutes." | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| decorators = [never_cache] | decorators = [never_cache] | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -1757,3 +1763,39 @@ def forbidden_view(request, exception=None, reason=''): | ||||||
|                 'again.') |                 'again.') | ||||||
|     messages.add_message(request, messages.ERROR, err_msg) |     messages.add_message(request, messages.ERROR, err_msg) | ||||||
|     return HttpResponseRedirect(request.get_full_path()) |     return HttpResponseRedirect(request.get_full_path()) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class CheckUserVM(APIView): | ||||||
|  |     renderer_classes = (JSONRenderer, ) | ||||||
|  | 
 | ||||||
|  |     def get(self, request): | ||||||
|  |         try: | ||||||
|  |             email = request.data['email'] | ||||||
|  |             ip = request.data['ip'] | ||||||
|  |             user = request.data['user'] | ||||||
|  |             realm = request.data['realm'] | ||||||
|  |             token = request.data['token'] | ||||||
|  |             if realm != settings.READ_VM_REALM: | ||||||
|  |                 return Response("User not allowed", 403) | ||||||
|  |             response = check_otp(user, realm, token) | ||||||
|  |             if response != 200: | ||||||
|  |                 return Response('Invalid token', 403) | ||||||
|  |             manager = OpenNebulaManager() | ||||||
|  |             # not the best way to lookup vms by ip | ||||||
|  |             # TODO: make this optimal | ||||||
|  |             vms = manager.get_vms() | ||||||
|  |             users_vms = [vm for vm in vms if vm.uname == email] | ||||||
|  |             if len(users_vms) == 0: | ||||||
|  |                 return Response('No VM found with the given email address', | ||||||
|  |                                 404) | ||||||
|  |             for vm in users_vms: | ||||||
|  |                 for nic in vm.template.nics: | ||||||
|  |                     if hasattr(nic, 'ip6_global'): | ||||||
|  |                         if nic.ip6_global == ip: | ||||||
|  |                             return Response('success', 200) | ||||||
|  |                     elif hasattr(nic, 'ip'): | ||||||
|  |                         if nic.ip == ip: | ||||||
|  |                             return Response('success', 200) | ||||||
|  |             return Response('No VM found matching the ip address provided', 404) | ||||||
|  |         except KeyError: | ||||||
|  |             return Response('Not enough data provided', 400) | ||||||
|  |  | ||||||
|  | @ -98,3 +98,4 @@ amqp==2.2.1 | ||||||
| vine==1.1.4 | vine==1.1.4 | ||||||
| cdist==5.0.1 | cdist==5.0.1 | ||||||
| git+https://github.com/ungleich/djangocms-multisite.git#egg=djangocms_multisite | git+https://github.com/ungleich/djangocms-multisite.git#egg=djangocms_multisite | ||||||
|  | pyotp | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue