Esempio n. 1
0
def check_settings(app_configs, **kwargs):
    errors = []

    # Ensure needed helpers are in INSTALLED_APPS.
    required_helper_apps = [
        'django.contrib.humanize', 'bootstrap3', 'colorfield', 'rest_framework'
    ]

    for app_name in required_helper_apps:
        if app_name not in settings.INSTALLED_APPS:
            errors.append(
                Error(MISSING_INSTALLED_APP_MSG.format(app_name, app_name),
                      id='assignment_desk.E001'))

    # Ensure django-bootstrap is configured as expected, including the
    # DMN-style "Immaterial" field renderers.
    bootstrap_config = getattr(settings, 'BOOTSTRAP3', None)
    if bootstrap_config and 'field_renderers' in bootstrap_config:
        required_field_renderers = ['default', 'inline', 'immaterial']

        for renderer_key in required_field_renderers:
            if renderer_key not in bootstrap_config['field_renderers']:
                errors.append(
                    Info(MISSING_RENDERER_MSG.format(renderer_key),
                         id='assignment_desk.E002b'))
    else:
        errors.append(Info(MISSING_BOOTSTRAP_MSG, id='assignment_desk.E002a'))

    return errors
Esempio n. 2
0
File: checks.py Progetto: czfgd/lava
def check_services(app_configs, **kwargs):

    errors = []
    services = [
        "apache2",
        "lava-server-gunicorn",
        "lava-master",
        "lava-publisher",
        "lava-logs",
        "postgresql",
    ]
    optional = ["lava-slave"]

    # check if systemd is running
    try:
        subprocess.check_output(["systemctl"], stderr=subprocess.PIPE)
        running_systemd = True
    except subprocess.CalledProcessError:
        running_systemd = False

    if running_systemd:
        # we can call systemctl
        for service in services:
            try:
                subprocess.check_call(  # nosec system
                    ["systemctl", "-q", "is-active", service]
                )
            except subprocess.CalledProcessError:
                errors.append(
                    Error("%s service is not active." % service, obj="lava services")
                )

        for service in optional:
            try:
                subprocess.check_call(  # nosec system
                    ["systemctl", "-q", "is-active", service]
                )
            except subprocess.CalledProcessError:
                errors.append(
                    Info("%s service is not active." % service, obj="lava services")
                )
    else:
        # systemd is not running, check /proc directly.
        daemons = find_our_daemons()
        for key, value in daemons.items():
            if key in services:
                if not value:
                    errors.append(
                        Error("%s daemon is not active." % key, obj="lava daemons")
                    )
            if key in optional:
                if not value:
                    errors.append(
                        Info("%s daemon is not active." % key, obj="lava daemons")
                    )
    return errors
Esempio n. 3
0
def recipe_signatures_use_good_certificates(app_configs, **kwargs):
    errors = []
    expire_early = None
    if settings.CERTIFICATES_EXPIRE_EARLY_DAYS:
        expire_early = timedelta(days=settings.CERTIFICATES_EXPIRE_EARLY_DAYS)

    try:
        Recipe = apps.get_model('recipes', 'Recipe')
        signed_recipes = list(Recipe.objects.exclude(signature=None))
    except (ProgrammingError, OperationalError, ImproperlyConfigured):
        errors.append(Info('Could not retrieve recipes', id=INFO_COULD_NOT_RETRIEVE_RECIPES))
    else:
        urls = set(r.signature.x5u for r in signed_recipes)
        for url in urls:
            try:
                signing.verify_x5u(url, expire_early)
            except signing.BadCertificate as exc:
                matching_recipes = Recipe.objects.filter(signature__x5u=url)
                count = matching_recipes.count()
                ids = ', '.join(str(r.id) for r in matching_recipes)
                msg = (f'{count} recipes (ids {ids}) are signed with a bad cert. {exc.detail}. '
                       f'Certificate url is {url}')
                errors.append(Warning(msg, id=WARNING_BAD_SIGNING_CERTIFICATE))

    return errors
Esempio n. 4
0
File: checks.py Progetto: czfgd/lava
def _package_status(name, errors, info=False):
    try:
        out = (
            subprocess.check_output(  # nosec system
                ["dpkg-query", "--status", name], stderr=subprocess.STDOUT
            )
            .decode("utf-8")
            .split("\n")
        )
        if out[1] != "Status: install ok installed":
            errors.append(
                Error("'%s' not installed correctly" % name, obj="debian pkg")
            )
    except FileNotFoundError:
        errors.append(Warning("Unable to query %s" % name, obj="debian pkg"))
    except subprocess.CalledProcessError:
        if info:
            errors.append(
                Info(
                    "'%s' not installed from a Debian package" % name, obj="debian pkg"
                )
            )
        else:
            errors.append(
                Error(
                    "'%s' not installed from a Debian package" % name, obj="debian pkg"
                )
            )
Esempio n. 5
0
def check_services(app_configs, **kwargs):

    errors = []
    services = [
        'apache2',
        'lava-server-gunicorn',
        'lava-master',
        'lava-publisher',
        'lava-logs',
        'postgresql',
    ]
    optional = [
        'lava-slave',
    ]

    for service in services:
        try:
            subprocess.check_call(['systemctl', '-q', 'is-active',
                                   service])  # nosec system
        except subprocess.CalledProcessError:
            errors.append(
                Error("%s service is not active." % service,
                      obj="lava service"))

    for service in optional:
        try:
            subprocess.check_call(['systemctl', '-q', 'is-active',
                                   service])  # nosec system
        except subprocess.CalledProcessError:
            errors.append(
                Info("%s service is not active." % service,
                     obj="lava service"))
    return errors
Esempio n. 6
0
def signatures_use_good_certificates(app_configs, **kwargs):
    errors = []
    expire_early = None
    if settings.CERTIFICATES_EXPIRE_EARLY_DAYS:
        expire_early = timedelta(days=settings.CERTIFICATES_EXPIRE_EARLY_DAYS)

    try:
        Signature = apps.get_model('recipes', 'Signature')
        Recipe = apps.get_model('recipes', 'Recipe')
        Action = apps.get_model('recipes', 'Action')
        signatures = list(Signature.objects.all())
    except (ProgrammingError, OperationalError, ImproperlyConfigured) as e:
        msg = f'Could not retrieve signatures: {e}'
        errors.append(Info(msg, id=INFO_COULD_NOT_RETRIEVE_SIGNATURES))
    else:
        urls = set(s.x5u for s in signatures)
        for url in urls:
            try:
                signing.verify_x5u(url, expire_early)
            except signing.BadCertificate as exc:
                matching_recipes = Recipe.objects.filter(signature__x5u=url)
                matching_actions = Action.objects.filter(signature__x5u=url)
                bad_objects = list(matching_recipes) + list(matching_actions)

                object_names = ', '.join(bad_objects)
                msg = (
                    f'{len(bad_objects)} objects are signed with a bad cert: {object_names}. '
                    f'{exc.detail}. Certificate url is {url}. ')
                errors.append(Warning(msg, id=WARNING_BAD_SIGNING_CERTIFICATE))

    return errors
Esempio n. 7
0
def check_version(app_configs=None, **kwargs):
    try:
        latest = get_latest_version()
    except (ValueError, IOError):
        return []
    if LooseVersion(latest.version) > LooseVersion(VERSION_BASE):
        # With release every two months, this get's triggered after three releases
        if latest.timestamp + timedelta(days=180) < datetime.now():
            return [
                Critical(
                    "You Weblate version is outdated, please upgrade to {}.".
                    format(latest.version),
                    hint=get_doc_url("admin/upgrade"),
                    id="weblate.C031",
                )
            ]
        return [
            Info(
                "New Weblate version is available, please upgrade to {}.".
                format(latest.version),
                hint=get_doc_url("admin/upgrade"),
                id="weblate.I031",
            )
        ]
    return []
Esempio n. 8
0
def check_backups(app_configs, **kwargs):
    from weblate.wladmin.models import BackupService

    errors = []
    if not BackupService.objects.filter(enabled=True).exists():
        errors.append(
            Info(
                "Backups are not configured, "
                "it is highly recommended for production use",
                hint=get_doc_url("admin/backup"),
                id="weblate.I028",
            ))
    for service in BackupService.objects.filter(enabled=True):
        try:
            last_log = service.last_logs()[0].event
        except IndexError:
            last_log = "error"
        if last_log == "error":
            errors.append(
                Critical(
                    "There was error while performing backups: {}".format(
                        last_log.log),
                    hint=get_doc_url("admin/backup"),
                    id="weblate.C029",
                ))
            break

    return errors
Esempio n. 9
0
def action_signatures_are_correct(app_configs, **kwargs):
    errors = []
    try:
        Action = apps.get_model("recipes", "Action")
        # pre-fetch signatures, to avoid race condition with deleted signatures
        signed_actions = list(
            Action.objects.exclude(signature=None).select_related("signature"))
    except (ProgrammingError, OperationalError, ImproperlyConfigured) as e:
        msg = f"Could not retrieve actions: f{e}"
        errors.append(Info(msg, id=INFO_COULD_NOT_RETRIEVE_ACTIONS))
        return errors

    try:
        for action in signed_actions:
            data = action.canonical_json()
            signature = action.signature.signature
            pubkey = action.signature.public_key
            try:
                signing.verify_signature(data, signature, pubkey)
            except signing.BadSignature as e:
                msg = f"Action '{action}' (id={action.id}) has a bad signature: {e.detail}"
                errors.append(Error(msg, id=ERROR_INVALID_ACTION_SIGNATURE))
    except (ProgrammingError, OperationalError, ImproperlyConfigured) as e:
        errors.append(
            Warning(f"Could not check signatures: {e}",
                    id=WARNING_COULD_NOT_CHECK_SIGNATURES))

    return errors
Esempio n. 10
0
def recipe_signatures_are_correct(app_configs, **kwargs):
    errors = []
    try:
        Recipe = apps.get_model("recipes", "Recipe")
        # pre-fetch signatures, to avoid race condition with deleted signatures
        signed_recipes = list(
            Recipe.objects.exclude(signature=None).select_related("signature"))
    except (ProgrammingError, OperationalError, ImproperlyConfigured) as e:
        errors.append(
            Info(f"Could not retrieve recipes: {e}",
                 id=INFO_COULD_NOT_RETRIEVE_RECIPES))
        return errors

    try:
        for recipe in signed_recipes:
            data = recipe.canonical_json()
            signature = recipe.signature.signature
            pubkey = recipe.signature.public_key
            try:
                signing.verify_signature(data, signature, pubkey)
            except signing.BadSignature as e:
                msg = "Recipe '{recipe}' (id={recipe.id}) has a bad signature: {detail}".format(
                    recipe=recipe, detail=e.detail)
                errors.append(Error(msg, id=ERROR_INVALID_RECIPE_SIGNATURE))
    except (ProgrammingError, OperationalError, ImproperlyConfigured) as e:
        errors.append(
            Warning(f"Could not check signatures: {e}",
                    id=WARNING_COULD_NOT_CHECK_SIGNATURES))

    return errors
Esempio n. 11
0
    def _migrate_legacy_clean_name(cls):
        """
        Ensure that existing data stored will be accessible via the legacy clean_name.
        When checks run, replace any blank clean_name values with the unidecode conversion.
        """

        try:
            objects = cls.objects.filter(clean_name__exact="")
            if objects.count() == 0:
                return None

        except (FieldError, DatabaseError):
            # attempting to query on clean_name before field has been added
            return None

        try:
            from unidecode import unidecode
        except ImportError as error:
            description = "You have form submission data that was created on an older version of Wagtail and requires the unidecode library to retrieve it correctly. Please install the unidecode package."
            raise Exception(description) from error

        for obj in objects:
            legacy_clean_name = str(slugify(str(unidecode(obj.label))))
            obj.clean_name = legacy_clean_name
            obj.save()

        return Info("Added `clean_name` on %s form field(s)" % objects.count(),
                    obj=cls)
Esempio n. 12
0
def migrations_applied(app_configs, **kwargs):
    from django.db.migrations.loader import MigrationLoader
    errors = []

    # Load migrations from disk/DB
    try:
        loader = MigrationLoader(connection, ignore_no_migrations=True)
    except (ImproperlyConfigured, ProgrammingError, OperationalError):
        msg = "Can't connect to database to check migrations"
        return [Info(msg, id=INFO_CANT_CHECK_MIGRATIONS)]
    graph = loader.graph

    if app_configs:
        app_labels = [app.label for app in app_configs]
    else:
        app_labels = loader.migrated_apps

    for node, migration in graph.nodes.items():
        if migration.app_label not in app_labels:
            continue
        if node not in loader.applied_migrations:
            msg = 'Unapplied migration {}'.format(migration)
            # NB: This *must* be a Warning, not an Error, because Errors
            # prevent migrations from being run.
            errors.append(Warning(msg, id=WARNING_UNAPPLIED_MIGRATION))

    return errors
    def check_payment_backend_settings(app_configs, **kwargs):
        from django.conf import settings
        errors = []

        config_errors = check_config(settings)
        for error in config_errors:
            errors.append(Info(**error))

        return errors
Esempio n. 14
0
    def test_form_field_clean_name_update_on_checks(self):
        fields_before_checks = [(
            field.label,
            field.clean_name,
        ) for field in FormFieldWithCustomSubmission.objects.all()]

        self.assertEqual(
            fields_before_checks,
            [
                ("Your email", ""),
                ("Your message", ""),
                ("Your choices", ""),
            ],
        )

        # running checks should show an info message AND update blank clean_name values

        messages = FormFieldWithCustomSubmission.check()

        self.assertEqual(
            messages,
            [
                Info(
                    "Added `clean_name` on 3 form field(s)",
                    obj=FormFieldWithCustomSubmission,
                )
            ],
        )

        fields_after_checks = [(
            field.label,
            field.clean_name,
        ) for field in FormFieldWithCustomSubmission.objects.all()]

        self.assertEqual(
            fields_after_checks,
            [
                ("Your email", "your-email"),  # kebab case, legacy format
                ("Your message", "your-message"),
                ("Your choices", "your-choices"),
            ],
        )

        # running checks again should return no messages as fields no longer need changing
        self.assertEqual(FormFieldWithCustomSubmission.check(), [])

        # creating a new field should use the non-legacy clean_name format

        field = FormFieldWithCustomSubmission.objects.create(
            page=self.form_page,
            label="Your FAVOURITE #number",
            field_type="number",
        )

        self.assertEqual(field.clean_name, "your_favourite_number")
Esempio n. 15
0
def check_errors(app_configs=None, **kwargs):
    """Check there is error collection configured."""
    if hasattr(settings, 'ROLLBAR') or hasattr(settings, 'RAVEN_CONFIG'):
        return []
    return [
        Info(
            'Error collection is not configured, it is highly recommended for production use',
            hint=get_doc_url('admin/install', 'collecting-errors'),
            id='weblate.I021',
        )
    ]
Esempio n. 16
0
def check_errors(app_configs=None, **kwargs):
    """Check there is error collection configured."""
    if (hasattr(settings, "ROLLBAR") or hasattr(settings, "RAVEN_CONFIG")
            or settings.SENTRY_DSN):
        return []
    return [
        Info(
            "Error collection is not configured, "
            "it is highly recommended for production use",
            hint=get_doc_url("admin/install", "collecting-errors"),
            id="weblate.I021",
        )
    ]
Esempio n. 17
0
def _package_status(name, errors, info=False):
    try:
        out = subprocess.check_output(
            ["dpkg-query", "--status", name],  # nosec system
            stderr=subprocess.STDOUT).decode("utf-8").split("\n")
        if out[1] != "Status: install ok installed":
            errors.append(Error('not installed correctly', obj=name))
    except subprocess.CalledProcessError:
        if info:
            errors.append(Info('not installed from a Debian package',
                               obj=name))
        else:
            errors.append(
                Error('not installed from a Debian package', obj=name))
Esempio n. 18
0
 def check_commandline(self):
     if psutil is None:
         return
     for y in psutil.disk_partitions(all=True):
         if y.mountpoint in self.excluded_mountpoints:
             continue
         # noinspection PyBroadException
         try:
             usage = psutil.disk_usage(y.mountpoint)
             if usage.total > 0 and usage.percent > 95:
                 msg = "%s is almost full (%s %%)." % (y.mountpoint, usage.percent)
                 settings_check_results.append(Info(msg, obj="system"))
         except Exception:
             pass
Esempio n. 19
0
def google_api_check(app_configs, **kwargs):
    errors = []

    if (app_configs is None or\
        apps.get_app_config('data_finder') in app_configs):

        if settings.GOOGLE_API_KEY == '':
            errors.append(
                Info(
                    "Google API Key is not set - usage limits will apply",
                    hint='Define GOOGLE_API_KEY as an env var or in local.py',
                    obj='data_finder',
                    id='data_finder.I002',
                ))
    return errors
Esempio n. 20
0
def mapit_ua_check(app_configs, **kwargs):
    errors = []

    if (app_configs is None or\
        apps.get_app_config('data_finder') in app_configs):

        if settings.MAPIT_UA is None:
            errors.append(
                Info(
                    "Mapit user agent is not set - usage limits will apply",
                    hint='Define MAPIT_UA as an env var or in local.py',
                    obj='data_finder',
                    id='data_finder.I001',
                ))
    return errors
Esempio n. 21
0
def actions_have_consistent_hashes(app_configs, **kwargs):
    errors = []
    try:
        Action = apps.get_model('recipes', 'Action')
        actions = list(Action.objects.all())
    except (ProgrammingError, OperationalError, ImproperlyConfigured):
        errors.append(Info('Could not retrieve actions', id=INFO_COULD_NOT_RETRIEVE_ACTIONS))
    else:
        for action in actions:
            if action.compute_implementation_hash() != action.implementation_hash:
                msg = ("Action '{action}' (id={action.id}) has a mismatched hash"
                       .format(action=action))
                errors.append(Warning(msg, id=WARNING_MISMATCHED_ACTION_HASH))

    return errors
Esempio n. 22
0
def google_api_check(app_configs, **kwargs):
    errors = []

    if app_configs is None or apps.get_app_config("data_finder") in app_configs:

        if not settings.GOOGLE_API_KEYS:
            errors.append(
                Info(
                    "No Google API Keys are set - usage limits will apply",
                    hint="Define GOOGLE_API_KEYS in local.py",
                    obj="data_finder",
                    id="data_finder.I002",
                )
            )
    return errors
Esempio n. 23
0
def actions_have_consistent_hashes(app_configs, **kwargs):
    errors = []
    try:
        Action = apps.get_model("recipes", "Action")
        actions = list(Action.objects.filter(implementation__isnull=False))
    except (ProgrammingError, OperationalError, ImproperlyConfigured) as e:
        errors.append(Info(f"Could not retrieve actions: {e}", id=INFO_COULD_NOT_RETRIEVE_ACTIONS))
    else:
        for action in actions:
            if action.compute_implementation_hash() != action.implementation_hash:
                msg = "Action '{action}' (id={action.id}) has a mismatched hash".format(
                    action=action
                )
                errors.append(Error(msg, id=ERROR_MISMATCHED_ACTION_HASH))

    return errors
Esempio n. 24
0
def signatures_use_good_certificates(app_configs, **kwargs):
    errors = []
    expire_early = None
    if settings.CERTIFICATES_EXPIRE_EARLY_DAYS:
        expire_early = timedelta(days=settings.CERTIFICATES_EXPIRE_EARLY_DAYS)

    try:
        Recipe = apps.get_model("recipes", "Recipe")
        Action = apps.get_model("recipes", "Action")

        urls = set()
        for recipe in Recipe.objects.exclude(signature=None):
            urls.add(recipe.signature.x5u)
        for action in Action.objects.exclude(signature=None):
            urls.add(action.signature.x5u)
    except (ProgrammingError, OperationalError, ImproperlyConfigured) as e:
        msg = f"Could not retrieve signatures: {e}"
        errors.append(Info(msg, id=INFO_COULD_NOT_RETRIEVE_SIGNATURES))
    else:

        def get_matching_object_names(url):
            matching_recipes = Recipe.objects.filter(signature__x5u=url)
            matching_actions = Action.objects.filter(signature__x5u=url)
            matching_objects = list(matching_recipes) + list(matching_actions)
            object_names = [str(o) for o in matching_objects]
            return object_names

        for url in urls:
            try:
                signing.verify_x5u(url, expire_early)
            except signing.BadCertificate as exc:
                bad_object_names = get_matching_object_names(url)
                msg = (
                    f"{len(bad_object_names)} objects are signed with a bad cert: "
                    f"{bad_object_names}. {exc.detail}. Certificate url is {url}. "
                )
                errors.append(Error(msg, id=ERROR_BAD_SIGNING_CERTIFICATE))
            except requests.RequestException as exc:
                bad_object_names = get_matching_object_names(url)
                msg = (
                    f"The certificate at {url} could not be fetched due to a network error to "
                    f"verify. {len(bad_object_names)} objects are signed with this certificate: "
                    f"{bad_object_names}. {exc}")
                errors.append(Error(msg,
                                    id=ERROR_COULD_NOT_VERIFY_CERTIFICATE))

    return errors
Esempio n. 25
0
File: checks.py Progetto: slawr/lava
def _package_status(name, info=False):
    try:
        out = (
            subprocess.check_output(  # nosec system
                ["dpkg-query", "--status", name],
                stderr=subprocess.STDOUT).decode("utf-8").split("\n"))
        if out[1] != "Status: install ok installed":
            return Error(f"'{name}' not installed correctly", obj="debian pkg")
    except FileNotFoundError:
        return Warning(f"Unable to query {name}", obj="debian pkg")
    except subprocess.CalledProcessError:
        if info:
            return Info(f"'{name}' not installed from a Debian package",
                        obj="debian pkg")
        else:
            return Error(f"'{name}' not installed from a Debian package",
                         obj="debian pkg")
Esempio n. 26
0
def signatures_use_good_certificates(app_configs, **kwargs):
    errors = []
    expire_early = None
    if settings.CERTIFICATES_EXPIRE_EARLY_DAYS:
        expire_early = timedelta(days=settings.CERTIFICATES_EXPIRE_EARLY_DAYS)

    try:
        Recipe = apps.get_model("recipes", "Recipe")
        Action = apps.get_model("recipes", "Action")

        x5u_urls = defaultdict(list)
        for recipe in Recipe.objects.exclude(
                signature__x5u=None).select_related("signature"):
            x5u_urls[recipe.signature.x5u].append(str(recipe))
        for action in Action.objects.exclude(
                signature__x5u=None).select_related("signature"):
            x5u_urls[action.signature.x5u].append(str(action))
    except (ProgrammingError, OperationalError, ImproperlyConfigured) as e:
        msg = f"Could not retrieve signatures: {e}"
        errors.append(Info(msg, id=INFO_COULD_NOT_RETRIEVE_SIGNATURES))
    else:

        for url in x5u_urls:
            try:
                signing.verify_x5u(url, expire_early)
            except signing.BadCertificate as exc:
                bad_object_names = x5u_urls[url]
                msg = (
                    f"{len(bad_object_names)} objects are signed with a bad cert: "
                    f"{bad_object_names}. {exc.detail}. Certificate url is {url}. "
                )
                errors.append(Error(msg, id=ERROR_BAD_SIGNING_CERTIFICATE))
            except requests.RequestException as exc:
                bad_object_names = x5u_urls[url]
                msg = (
                    f"The certificate at {url} could not be fetched due to a network error to "
                    f"verify. {len(bad_object_names)} objects are signed with this certificate: "
                    f"{bad_object_names}. {exc}")
                errors.append(Error(msg,
                                    id=ERROR_COULD_NOT_VERIFY_CERTIFICATE))

    return errors
Esempio n. 27
0
def recipe_signatures_are_correct(app_configs, **kwargs):
    errors = []
    try:
        Recipe = apps.get_model('recipes', 'Recipe')
        signed_recipes = list(Recipe.objects.exclude(signature=None))
    except (ProgrammingError, OperationalError, ImproperlyConfigured):
        errors.append(Info('Could not retrieve recipes', id=INFO_COULD_NOT_RETRIEVE_RECIPES))
    else:
        for recipe in signed_recipes:
            data = recipe.canonical_json()
            signature = recipe.signature.signature
            pubkey = recipe.signature.public_key
            try:
                signing.verify_signature(data, signature, pubkey)
            except signing.BadSignature as e:
                msg = ("Recipe '{recipe}' (id={recipe.id}) has a bad signature: {detail}"
                       .format(recipe=recipe, detail=e.detail))
                errors.append(Warning(msg, id=WARNING_INVALID_RECIPE_SIGNATURE))

    return errors
Esempio n. 28
0
def action_signatures_are_correct(app_configs, **kwargs):
    errors = []
    try:
        Action = apps.get_model('recipes', 'Action')
        signed_actions = list(Action.objects.exclude(signature=None))
    except (ProgrammingError, OperationalError, ImproperlyConfigured) as e:
        msg = f'Could not retrieve actions: f{e}'
        errors.append(Info(msg, id=INFO_COULD_NOT_RETRIEVE_ACTIONS))
    else:
        for action in signed_actions:
            data = action.canonical_json()
            signature = action.signature.signature
            pubkey = action.signature.public_key
            try:
                signing.verify_signature(data, signature, pubkey)
            except signing.BadSignature as e:
                msg = f"Action '{action}' (id={action.id}) has a bad signature: {e.detail}"
                errors.append(Warning(msg,
                                      id=WARNING_INVALID_ACTION_SIGNATURE))

    return errors
Esempio n. 29
0
def recipe_signatures_are_correct(app_configs, **kwargs):
    errors = []
    try:
        Recipe = apps.get_model("recipes", "Recipe")
        # pre-fetch signatures, to avoid race condition with deleted signatures
        signed_recipes = list(
            Recipe.objects.exclude(signature=None).select_related("signature"))
    except (ProgrammingError, OperationalError, ImproperlyConfigured) as e:
        errors.append(
            Info(f"Could not retrieve recipes: {e}",
                 id=INFO_COULD_NOT_RETRIEVE_RECIPES))
        return errors

    try:
        for recipe in signed_recipes:
            data = recipe.canonical_json()
            signature = recipe.signature.signature
            pubkey = recipe.signature.public_key
            x5u = recipe.signature.x5u
            try:
                if x5u:
                    signing.verify_signature_x5u(data, signature, x5u)
                else:
                    signing.verify_signature_pubkey(data, signature, pubkey)
            except signing.BadSignature as e:
                msg = "Recipe '{recipe}' (id={recipe.id}) has a bad signature: {detail}".format(
                    recipe=recipe, detail=e.detail)
                errors.append(Error(msg, id=ERROR_INVALID_RECIPE_SIGNATURE))
            except requests.RequestException as exc:
                msg = (
                    f"The signature for recipe with ID {recipe.id} could not be be verified due to "
                    f"network error when requesting the url {x5u!r}. {exc}")
                errors.append(Error(msg,
                                    id=ERROR_COULD_NOT_VERIFY_CERTIFICATE))
    except (ProgrammingError, OperationalError, ImproperlyConfigured) as e:
        errors.append(
            Warning(f"Could not check signatures: {e}",
                    id=WARNING_COULD_NOT_CHECK_SIGNATURES))

    return errors
def check_settings(app_configs, **kwargs):
    """ Check that settings are implemented properly for 9cms
    :param app_configs: a list of apps to be checks or None for all
    :param kwargs: keyword arguments
    :return: a list of errors
    """
    checks = []
    if not settings.MEDIA_ROOT:
        msg = (
            "No media root is specified in settings. A media folder is necessary for the user to upload images. "
            "You can specify one in the settings file as eg: `MEDIA_ROOT = os.path.join(BASE_DIR, 'media')`."
        )
        checks.append(Info(msg, id='ninecms.I001'))
    if not settings.MEDIA_URL:
        msg = (
            "No media url is specified in settings. A media url is necessary for 9cms to display uploaded images. "
            "You can specify one in the settings file as eg: `MEDIA_URL = '/media/'`."
        )
        checks.append(Info(msg, id='ninecms.I002'))
    if not settings.ADMINS:
        msg = (
            "No administrator emails are specified in settings. These are necessary for 9cms to send information "
            "on updates if a cron is setup. You can specify them in the settings file as eg: "
            "`ADMINS = (('Webmaster', '*****@*****.**'),)`.")
        checks.append(Info(msg, id='ninecms.I003'))
    if not settings.MANAGERS:
        msg = (
            "No manager emails are specified in settings. These are necessary for 9cms to messages through the "
            "contact form. You can specify them in the settings file as eg: "
            "`MANAGERS = (('Webmaster', '*****@*****.**'),)`.")
        checks.append(Info(msg, id='ninecms.I004'))
    if settings.SESSION_COOKIE_NAME == 'sessionid':
        msg = (
            "It is advised that you specify a session cookie name other than the default, especially in shared "
            "hosting environments. You can specify this in the settings file as eg: "
            "`SESSION_COOKIE_NAME = 'myapp_sessionid'`.")
        checks.append(Info(msg, id='ninecms.I005'))
    if settings.CACHES['default'][
            'BACKEND'] == 'django.core.cache.backends.memcached.MemcachedCache':
        if not settings.CACHES['default']['KEY_PREFIX']:
            msg = (
                "It is advised that you specify a cache key prefix for the default memcached, especially in shared "
                "hosting environments. You can specify this in the settings file with "
                "``settings.CACHES['default']['KEY_PREFIX']`.")
            checks.append(Info(msg, id='ninecms.I006'))
    return checks