示例#1
0
    def form_valid(self, form):
        try:
            self.object = form.save(commit=False)
            self.object.service = self.service
            self.object.save()
        except Exception:
            form.add_error(None, "A Unix Group already exists with that name")
            return self.form_invalid(form)

        unix_users = list(
            set(validate_crsid_list(self.request.POST.getlist('unix_users'))))

        if not all(
                user in self.object.service.site.list_of_all_type_of_users()
                for user in unix_users):
            form.add_error(
                None,
                "You have added users to this group that are not in the authorisation user list."
            )
            return self.form_invalid(form)

        self.object.users.add(*unix_users)

        launch_ansible(self.service)  # to apply these changes to the vm
        return super(UnixGroupCreate, self).form_valid(form)
示例#2
0
 def accept_it(self):
     self.status = 'accepted'
     self.save()
     if self.vhost.main_domain is None or \
                     self.vhost.main_domain.name == self.vhost.service.network_configuration.name:
         self.vhost.main_domain = self
         self.vhost.save()
     from apimws.ipreg import set_cname
     try:
         set_cname(self.name, self.vhost.service.network_configuration.name)
     except DomainNameDelegatedException:
         return self.reject_it("Domain delegated")
     from apimws.ansible import launch_ansible
     launch_ansible(self.vhost.service)
     now = datetime.now()
     # Check if the set_cname was executed before the DNS refresh of the current hour.
     # DNS refreshes happen at 53 minutes of each hour
     if now.minute > 55:
         # If it was executed after the DNS refresh of the current hour, send the email to the user when
         # the next refresh happens
         eta = now.replace(minute=54) + timedelta(hours=1)
     else:
         # If it was executed before the DNS refresh of the current hour, send the email to the user when
         # the refresh happens
         eta = now.replace(minute=54)
     from apimws.utils import domain_confirmation_user
     domain_confirmation_user.apply_async(args=[
         self,
     ], eta=eta)
示例#3
0
def quarantine(request, service_id):
    service = get_object_or_404(Service, pk=service_id)
    site = privileges_check(service.site.id, request.user)

    if site is None:
        return HttpResponseForbidden()

    if not service or not service.active or service.is_busy:
        return redirect(site)

    breadcrumbs = {
        0: dict(name='Managed Web Service server: ' + str(site.name), url=site.get_absolute_url()),
        1: dict(name='Server settings' if service.primary else 'Test server settings',
                url=reverse(service_settings, kwargs={'service_id': service.id})),
        2: dict(name='Quarantine', url=reverse(quarantine, kwargs={'service_id': service.id})),
    }

    parameters = {
        'breadcrumbs': breadcrumbs,
        'service': service,
        'site': site,
        'sidebar_messages': warning_messages(site),
    }

    if request.method == 'POST' and not site.is_admin_suspended():
        if request.POST['quarantine'] == "Quarantine":
            service.quarantined = True
        else:
            service.quarantined = False
        service.save()
        launch_ansible(service)
        return redirect(site)

    return render(request, 'mws/quarantine.html', parameters)
示例#4
0
def expire_domains():
    '''
    Periodically send messages to domain administrators about deleted domains and
    delete them after grace_days
    '''
    grace_days = settings.MWS_DOMAIN_NAME_GRACE_DAYS
    notify_days = list(range(1, grace_days, grace_days // 3 + 1))
    support_email = settings.EMAIL_MWS3_SUPPORT
    for domainname in DomainName.objects.filter(status='deleted').annotate(
            expired=(now() - F('updated_at'))):
        vhost = domainname.vhost
        service = domainname.vhost.service
        site = domainname.vhost.service.site
        if domainname.expired.days >= grace_days:
            EmailMessage(
                subject="MWS hostname %s deleted " % (domainname.name),
                body="This message is to inform you that the hostname\n%s\n"
                "associated with the %s website on the %s MWS server "
                "has failed validation for %d days, therefore it has been removed from the website.\n"
                "If you did not want this to happen you will need to make sure the hostname exists "
                "before contacting us at %s" %
                (domainname.name, vhost.name, site.name,
                 domainname.expired.days, support_email),
                from_email="Managed Web Service Support <%s>" %
                getattr(settings, 'EMAIL_MWS3_SUPPORT',
                        '*****@*****.**'),
                to=[site.email],
                headers={
                    'Return-Path':
                    getattr(settings, 'EMAIL_MWS3_SUPPORT',
                            '*****@*****.**')
                }).send()
            LOGGER.warning('deleting DomainName {}'.format(domainname.name))
            domainname.delete()
            launch_ansible(service)
        elif domainname.expired.days in notify_days:
            on = domainname.updated_at + timedelta(days=grace_days)
            LOGGER.info('sending warning email for {} to {}'.format(
                domainname.name, site.email))
            EmailMessage(
                subject="MWS hostname %s scheduled for deletion " %
                (domainname.name),
                body="This message is to inform you that the hostname\n%s\n"
                "associated with the %s website on the %s MWS server "
                "has failed validation and is now scheduled for removal on %s.\n"
                "If you do not want this to happen you will need to ensure the hostname exists "
                "and is any one of\n - a CNAME pointing to the host %s;\n - an A record with address %s;\n"
                " - an AAAA record with address %s.\n" %
                (domainname.name, vhost.name, site.name, on.date().isoformat(),
                 service.hostname, service.ipv4, service.ipv6),
                from_email="Managed Web Service Support <%s>" %
                getattr(settings, 'EMAIL_MWS3_SUPPORT',
                        '*****@*****.**'),
                to=[site.email],
                headers={
                    'Return-Path':
                    getattr(settings, 'EMAIL_MWS3_SUPPORT',
                            '*****@*****.**')
                }).send()
示例#5
0
 def delete(self, request, *args, **kwargs):
     if self.domain.name != self.domain.vhost.service.network_configuration.name:
         if self.domain != self.domain.vhost.main_domain or self.domain.vhost.domain_names.count(
         ) == 1:
             self.domain.delete()
             launch_ansible(self.service)
             return HttpResponse()
     return HttpResponseForbidden()
示例#6
0
 def form_valid(self, form):
     try:
         self.object = form.save(commit=False)
         self.object.service = self.service
         self.object.save()
         launch_ansible(
             self.service)  # to create a new vhost configuration file
         return HttpResponseRedirect(self.get_success_url())
     except IntegrityError:
         messages.error(self.request, 'This website name already exists')
         return redirect(self.get_success_url())
示例#7
0
def php_libs(request, service_id):
    service = get_object_or_404(Service, pk=service_id)
    site = privileges_check(service.site.id, request.user)

    if site is None:
        return HttpResponseForbidden()

    if not service or not service.active or service.is_busy:
        return redirect(site)

    breadcrumbs = {
        0:
        dict(name='Managed Web Service server: ' + str(site.name),
             url=site.get_absolute_url()),
        1:
        dict(name='Server settings'
             if service.primary else 'Test server settings',
             url=reverse(service_settings, kwargs={'service_id': service.id})),
        2:
        dict(name='PHP Libraries',
             url=reverse(php_libs, kwargs={'service_id': service.id})),
    }

    from apimws.forms import PHPLibForm

    parameters = {
        'breadcrumbs':
        breadcrumbs,
        'service':
        service,
        'site':
        site,
        'sidebar_messages':
        warning_messages(site),
        'form':
        PHPLibForm(initial={
            'php_libs':
            list(service.php_libs.values_list('name', flat=True))
        }),
    }

    if request.method == 'POST':
        f = PHPLibForm(request.POST)
        if f.is_valid():
            service.php_libs.set(PHPLib.objects.filter(
                name__in=f.cleaned_data['php_libs']).all(),
                                 clear=True)
            service.save()
            launch_ansible(service)

    return render(request, 'mws/phplibs.html', parameters)
示例#8
0
 def delete(self, request, *args, **kwargs):
     vhost_name = self.vhost.name
     webapp = self.vhost.webapp
     service = self.vhost.service
     if vhost_name != "default":
         delete_vhost_ansible.delay(service, vhost_name, webapp)
         super(VhostDelete, self).delete(request, *args, **kwargs)
         launch_ansible(service)
         return HttpResponse(
             "The website/vhost '%s' has been deleted successfully" %
             vhost_name)
     else:
         return HttpResponseForbidden(
             "The default website/vhost cannot be deleted")
示例#9
0
def generate_csr(request, vhost_id):
    vhost = get_object_or_404(Vhost, pk=vhost_id)
    site = privileges_check(vhost.service.site.id, request.user)

    if request.method == 'POST' and vhost.tls_key_hash != 'requested' and vhost.tls_key_hash != 'renewal':
        if vhost.main_domain is None:
            breadcrumbs = {
                0:
                dict(name='Managed Web Service server: ' + str(site.name),
                     url=site.get_absolute_url()),
                1:
                dict(name='Server settings'
                     if vhost.service.primary else 'Test server settings',
                     url=reverse('sitesmanagement.views.service_settings',
                                 kwargs={'service_id': vhost.service.id})),
                2:
                dict(name='Vhosts Management: %s' % vhost.name,
                     url=reverse('listvhost',
                                 kwargs={'service_id': vhost.service.id})),
                3:
                dict(name='TLS/SSL Certificates',
                     url=reverse(certificates, kwargs={'vhost_id': vhost.id})),
            }

            return render(
                request, 'mws/certificates.html', {
                    'breadcrumbs': breadcrumbs,
                    'vhost': vhost,
                    'service': vhost.service,
                    'site': site,
                    'error_main_domain': True
                })

        if vhost.tls_enabled:
            vhost.tls_key_hash = 'renewal'
            vhost.csr = None
            vhost.save()
        else:
            vhost.tls_key_hash = 'requested'
            vhost.certificate = None
            vhost.csr = None
            vhost.tls_enabled = False
            vhost.save()

        launch_ansible(vhost.service)

    return redirect(reverse(certificates, kwargs={'vhost_id': vhost.id}))
示例#10
0
    def switch_services(self):
        prod_service = self.production_service
        test_service = self.test_service
        netconf_prod = prod_service.network_configuration
        netconf_test = test_service.network_configuration
        vhost_prod = prod_service.vhosts.all()
        ug_prod = prod_service.unix_groups.all()

        with transaction.atomic():
            # Switch vhosts, test service has no vhosts
            for vhost in vhost_prod:
                vhost.service = test_service
                vhost.save()

            # Switch unix groups, test service has no UG
            for ug in ug_prod:
                ug.service = test_service
                ug.save()

            # Switch network configuration
            test_service.network_configuration = NetworkConfig.get_free_test_service_config(
            )
            test_service.type = "production"
            test_service.site = None
            test_service.save()
            prod_service.network_configuration = netconf_test
            prod_service.type = "test"
            prod_service.save()
            test_service.site = self
            test_service.network_configuration = netconf_prod
            test_service.save()

            from apimws.models import AnsibleConfiguration
            AnsibleConfiguration.objects.update_or_create(
                service=test_service,
                key="backup_first_date",
                value=date.today().isoformat())

        from apimws.ansible import launch_ansible
        launch_ansible(prod_service)
        launch_ansible(test_service)
        return True
示例#11
0
    def form_valid(self, form):
        self.object = form.save()

        unix_users = list(
            set(validate_crsid_list(self.request.POST.getlist('unix_users'))))

        if not all(
                user in self.object.service.site.list_of_all_type_of_users()
                for user in unix_users):
            form.add_error(
                None,
                "You have added users to this group that are not in the authorisation user list."
            )
            return self.form_invalid(form)

        self.object.users.clear()
        self.object.users.add(*unix_users)

        launch_ansible(self.service)  # to apply these changes to the vm
        return super(UnixGroupUpdate, self).form_valid(form)
示例#12
0
def set_dn_as_main(request, domain_id):
    """View(Controller) to set the domain name selected as the main domain of the vhost"""
    domain = get_object_or_404(DomainName, pk=domain_id)
    vhost = domain.vhost
    site = privileges_check(vhost.service.site.id, request.user)
    service = vhost.service

    if site is None:
        return HttpResponseForbidden()

    if not service or not service.active or service.is_busy:
        return redirect(site)

    if request.method == 'POST':
        vhost.main_domain = domain
        vhost.save()
        launch_ansible(
            vhost.service
        )  # to update the vhost main domain name in the apache configuration

    return HttpResponseRedirect(
        reverse('listdomains', kwargs={'vhost_id': vhost.id}))
示例#13
0
def certificates(request, vhost_id):
    vhost = get_object_or_404(Vhost, pk=vhost_id)
    site = privileges_check(vhost.service.site.id, request.user)
    service = vhost.service

    if site is None:
        return HttpResponseForbidden()

    if not service or not service.active or service.is_busy:
        return redirect(site)

    if not vhost.domain_names.all():
        return redirect(
            reverse('listvhost', kwargs={'service_id': vhost.service.id}))

    breadcrumbs = {
        0:
        dict(name='Managed Web Service server: ' + str(site.name),
             url=site.get_absolute_url()),
        1:
        dict(name='Server settings'
             if vhost.service.primary else 'Test server settings',
             url=reverse('sitesmanagement.views.service_settings',
                         kwargs={'service_id': vhost.service.id})),
        2:
        dict(name='Web sites management: %s' % vhost.name,
             url=reverse('listvhost', kwargs={'service_id':
                                              vhost.service.id})),
        3:
        dict(name='TLS/SSL Certificate',
             url=reverse(certificates, kwargs={'vhost_id': vhost.id})),
    }

    error_message = None

    if request.method == 'POST':
        try:
            if 'cert' in request.FILES:
                try:
                    certificates_str = request.FILES['cert'].file.read()
                    cert = crypto.load_certificate(crypto.FILETYPE_PEM,
                                                   certificates_str)
                except Exception as e:
                    raise ValidationError("The certificate file is invalid")

                if vhost.csr is None:
                    raise ValidationError("CSR does not exists")

                if not csr_match_crt(vhost.csr, certificates_str):
                    raise ValidationError(
                        "The certificate doesn't match the CSR")

                issuer = None
                for component in cert.get_issuer().get_components():
                    if component[0] == 'CN':
                        issuer = component[1]
                if not issuer:
                    raise ValidationError(
                        "The certificate doesn't have any issuer")
                if issuer not in CERTIFICATE_CHAINS:
                    raise ValidationError("Certificate issuer unknown by MWS")

                vhost.certificate = certificates_str
                vhost.certificate_chain = CERTIFICATE_CHAINS[issuer]
                vhost.tls_enabled = True
                if vhost.tls_key_hash == 'renewal_waiting_cert':
                    vhost.tls_key_hash = 'renewal_cert'
                vhost.save()
                launch_ansible(service)
            else:
                raise ValidationError("No Certificate uploaded")
        except ValidationError as e:
            error_message = e.message

    return render(
        request, 'mws/certificates.html', {
            'breadcrumbs': breadcrumbs,
            'vhost': vhost,
            'service': vhost.service,
            'site': site,
            'sidebar_messages': warning_messages(site),
            'error_message': error_message
        })
示例#14
0
 def delete(self, request, *args, **kwargs):
     self.object = self.get_object()
     self.object.to_be_deleted = True
     self.object.save()
     launch_ansible(self.service)
     return HttpResponse()
示例#15
0
def execute_ansible(modeladmin, request, queryset):
    from apimws.ansible import launch_ansible
    for service in queryset:
        launch_ansible(service)
示例#16
0
def clone_vm_api_call(site):
    service = site.test_service
    host_network_configuration = NetworkConfig.get_free_host_config()
    parameters = {}
    parameters["site-id"] = "mwssite-%d" % service.site.id
    parameters["os"] = getattr(settings, 'OS_VERSION', "stretch")

    if host_network_configuration:
        netconf = {}
        if host_network_configuration.IPv4:
            netconf["IPv4"] = host_network_configuration.IPv4
        if host_network_configuration.IPv6:
            netconf["IPv6"] = host_network_configuration.IPv6
        if host_network_configuration.name:
            netconf["hostname"] = host_network_configuration.name
        vm = VirtualMachine.objects.create(
            service=service,
            token=uuid.uuid4(),
            network_configuration=host_network_configuration,
            cluster=which_cluster())
    else:
        raise AttributeError("No host network configuration")

    parameters["netconf"] = netconf
    parameters["callback"] = {
        "endpoint":
        "%s%s" % (settings.MAIN_DOMAIN, reverse(post_installation)),
        "vm_id": vm.id,
        "secret": str(vm.token),
    }

    parameters["features"] = {
        "cpu": service.site.type.numcpu,
        "ram": service.site.type.sizeram * 1024,
        "disk": service.site.type.sizedisk,
    }

    service.status = 'installing'
    service.save()

    response = vm_api_request(command='create', parameters=parameters, vm=vm)

    try:
        jresponse = json.loads(response)
    except ValueError as e:
        LOGGER.error("VM API response is not properly formated: %s", response)
        vm.name = vm.network_configuration.name
        vm.save()
        raise e

    try:
        if 'vmid' in jresponse:
            vm.name = jresponse['vmid']
        else:
            vm.name = vm.network_configuration.name
    except Exception as e:
        vm.name = vm.network_configuration.name
    vm.save()
    from apimws.models import AnsibleConfiguration
    AnsibleConfiguration.objects.update_or_create(
        service=service,
        key='os',
        defaults={'value': getattr(settings, "OS_VERSION", "stretch")})
    secrets_prealocation_vm(vm)

    # PHPLibs
    for phplib in site.production_service.php_libs.all():
        phplib.services.add(site.test_service)

    # Call Ansible to update the state of the machine
    launch_ansible(site.production_service)
    launch_ansible(site.test_service)

    return True
示例#17
0
def add_domain(request, vhost_id, socket_error=None):
    """View(Controller) to add a domain name to the vhost selected. """
    vhost = get_object_or_404(Vhost, pk=vhost_id)
    site = privileges_check(vhost.service.site.id, request.user)
    service = vhost.service

    if site is None:
        return HttpResponseForbidden()

    if not service or not service.active or service.is_busy:
        return redirect(site)

    if request.method == 'POST':
        domain_form = DomainNameFormNew(request.POST)
        if domain_form.is_valid():
            domain_requested = domain_form.save(commit=False)
            if domain_requested.name != '':
                if is_camacuk(domain_requested.name):
                    if domain_requested.name.endswith(
                            ".usertest.mws3.csx.cam.ac.uk"):
                        new_domain = DomainName.objects.create(
                            name=domain_requested.name,
                            status='accepted',
                            vhost=vhost,
                            requested_by=request.user)
                        new_domain.accept_it()
                    elif domain_requested.name.endswith(".mws3.csx.cam.ac.uk"):
                        new_domain = DomainName.objects.create(
                            name=domain_requested.name,
                            status='denied',
                            vhost=vhost,
                            requested_by=request.user)
                    elif 'special_case' in domain_form.data:
                        new_domain = DomainName.objects.create(
                            name=domain_requested.name,
                            status='special',
                            vhost=vhost,
                            requested_by=request.user,
                            reject_reason="User marked as special")
                    else:
                        new_domain = DomainName.objects.create(
                            name=domain_requested.name,
                            status='requested',
                            vhost=vhost,
                            requested_by=request.user)
                        ip_register_api_request.delay(new_domain)
                else:
                    new_domain = DomainName.objects.create(
                        name=domain_requested.name,
                        status='external',
                        vhost=vhost,
                        requested_by=request.user)
                    if vhost.main_domain is None or \
                                    vhost.main_domain.name == vhost.service.network_configuration.name:
                        vhost.main_domain = new_domain
                        vhost.save()
                launch_ansible(
                    vhost.service
                )  # to add the new domain name to the vhost apache configuration
        else:
            breadcrumbs = {
                0:
                dict(name='Managed Web Service server: ' + str(site.name),
                     url=site.get_absolute_url()),
                1:
                dict(name='Server settings'
                     if vhost.service.primary else 'Test server settings',
                     url=reverse('sitesmanagement.views.service_settings',
                                 kwargs={'service_id': vhost.service.id})),
                2:
                dict(name='Web sites management: %s' % vhost.name,
                     url=reverse('listvhost',
                                 kwargs={'service_id': vhost.service.id})),
                3:
                dict(name='Domain Names management',
                     url=reverse('listdomains', kwargs={'vhost_id': vhost.id}))
            }

            return render(
                request, 'mws/domains.html', {
                    'breadcrumbs': breadcrumbs,
                    'vhost': vhost,
                    'site': site,
                    'service': vhost.service,
                    'domain_form': domain_form,
                    'error': True
                })

    return redirect(reverse('listdomains', kwargs={'vhost_id': vhost.id}))