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