-
-
Notifications
You must be signed in to change notification settings - Fork 578
Add Unprotect.it API support for YARA rules. Closes #1711 #3229
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from 44 commits
ebcb5bd
ed8b40c
71d565b
8fce32c
22aba08
da4790b
2a4d5c1
1c36732
f36c978
4c70bf4
0463ae5
ca58db2
269603a
823d711
cb102bb
2428c05
5c46165
4f1927c
2c6c21f
11f58bd
3d0b72b
b6a2591
00f31eb
39a300a
bce5abd
9a3f4f6
a06790b
b379d8a
8cb1214
7ae4b6f
434703e
b9b467e
c0dc947
3dafbdc
8635c1e
ec6255c
b1d11bc
4168a2b
3a8aaaa
8bc5f8e
3d9382b
4bb3957
d066550
5089041
fe33d01
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -84,9 +84,15 @@ def directory(self) -> PosixPath: | |||||||||||||||||||||||||||||||||||||||
| self._directory = path / directory_name | ||||||||||||||||||||||||||||||||||||||||
| return self._directory | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
59
to
85
|
||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| def is_unprotect_api(self) -> bool: | ||||||||||||||||||||||||||||||||||||||||
| return "unprotect.it/api/detection_rules" in self.url | ||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok but we also want to have these rules added in the default parameter of this analyzer. You need to do a migration to update the list of available rules. |
||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+87
to
+89
|
||||||||||||||||||||||||||||||||||||||||
| def update(self): | ||||||||||||||||||||||||||||||||||||||||
| logger.info(f"Starting update of {self.url}") | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+87
to
91
|
||||||||||||||||||||||||||||||||||||||||
| if self.is_zip(): | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| if self.is_unprotect_api(): | ||||||||||||||||||||||||||||||||||||||||
| self._update_unprotect_api() | ||||||||||||||||||||||||||||||||||||||||
| elif self.is_zip(): | ||||||||||||||||||||||||||||||||||||||||
mlodic marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||
| # private url not supported at the moment for private | ||||||||||||||||||||||||||||||||||||||||
| self._update_zip() | ||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -149,6 +155,56 @@ def _update_git(self): | |||||||||||||||||||||||||||||||||||||||
| if settings.GIT_KEY_PATH.exists(): | ||||||||||||||||||||||||||||||||||||||||
| os.remove(settings.GIT_KEY_PATH) | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| # NEW:Unprotect.it API update logic | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
| # NEW:Unprotect.it API update logic |
Copilot
AI
Jan 23, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_update_unprotect_api() writes new .yar files but never removes existing rule files in self.directory. If rules are removed/renamed upstream, stale local .yar files will keep being compiled and scanned. Consider deleting existing .yar/.yara/.rule files (and compiled .yas) in this directory before fetching pages to ensure the local set matches the API snapshot.
| # Ensure local rules mirror the current Unprotect.it snapshot by | |
| # removing any existing YARA rule/compiled files before fetching. | |
| if hasattr(self, "directory"): | |
| try: | |
| for pattern in ("*.yar", "*.yara", "*.rule", "*.yas"): | |
| for existing_file in self.directory.glob(pattern): | |
| try: | |
| os.remove(existing_file) | |
| except OSError: | |
| logger.warning( | |
| "Failed to remove stale rule file %s", existing_file | |
| ) | |
| except Exception: | |
| # Log and continue; fetching new rules is still attempted. | |
| logger.exception( | |
| "Unexpected error while cleaning up existing Unprotect.it rules" | |
| ) |
Copilot
AI
Jan 27, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_update_unprotect_api() writes rules into a persistent unprotect_api/ directory but never clears previously downloaded rule files. This can leave stale rules around when they are removed/renamed upstream. Before writing new rules, consider cleaning the target directory (or writing to a temp dir and swapping) to keep local state consistent with the API.
Copilot
AI
Feb 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The directory creation and rule writing don't handle cleanup of old rules from previous runs. If a rule is removed from the Unprotect.it API, the old .yar file will remain on disk. Consider clearing the directory before fetching new rules, or implementing a mechanism to track and remove stale rules. This is important to prevent outdated or removed rules from being compiled and used in analysis.
| # Clean up stale YARA rule files from previous runs so only current | |
| # Unprotect.it rules are present in this directory. | |
| try: | |
| if base_dir.exists(): | |
| for existing_file in base_dir.glob("*.yar"): | |
| try: | |
| existing_file.unlink() | |
| except Exception: | |
| logger.warning("Failed to remove stale YARA rule file: %s", existing_file) | |
| except Exception: | |
| logger.exception("Failed to clean Unprotect.it rules directory: %s", base_dir) |
Copilot
AI
Feb 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_update_unprotect_api() writes the latest rules but never removes files from previous runs, so deleted/renamed rules in the API will remain on disk and keep getting compiled. Consider clearing base_dir (or rewriting into a temp dir and swapping) before writing the newly fetched rules.
Copilot
AI
Feb 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The MAX_PAGES constant is hardcoded to 20. If the Unprotect.it API returns more than 20 pages of results, some YARA rules will be silently skipped. Consider either: (1) removing the limit and fetching all pages, (2) making it configurable as a parameter, or (3) at minimum, logging a warning when the page limit is reached to alert users that not all rules were fetched. This is important for transparency and to prevent unexpected behavior when the API grows.
Copilot
AI
Jan 27, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unprotect.it API support introduces new network/pagination behavior but there are no unit tests covering it. Please add a unit test under tests/api_app/analyzers_manager/unit_tests/file_analyzers/ that mocks the paginated requests.get responses and asserts only YARA rules are written/compiled.
Copilot
AI
Feb 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new Unprotect.it code path (_update_unprotect_api) is not covered by tests. Add/extend a unit test (similar to tests/api_app/analyzers_manager/unit_tests/file_analyzers/test_yara_scan.py) that mocks requests.get to return paginated results/next responses and verifies only type.name == "YARA" rules are written and compiled.
Copilot
AI
Feb 18, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The exception handling here catches all exceptions with a bare "except Exception" and breaks the loop, potentially leaving the update incomplete. Additionally, the error is only logged but not re-raised, which could make it difficult to detect failures. Consider being more specific about which exceptions to catch (e.g., requests.RequestException, requests.Timeout) and potentially re-raising critical errors after logging. Also, the break statement means if page 5 fails, pages 6-20 won't be attempted, which may not be the desired behavior.
Copilot
AI
Jan 23, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New Unprotect.it pagination/filtering behavior isn’t covered by tests. Given existing tests for YaraScan (e.g., tests/api_app/analyzers_manager/unit_tests/file_analyzers/test_yara_scan.py and cron updater tests), add a unit test for _update_unprotect_api() that mocks paginated requests.get responses, verifies YARA-only filtering, and asserts files are written/updated correctly (including cleanup of stale rules if implemented).
Copilot
AI
Feb 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The safe_name sanitization only replaces a limited set of characters. While it handles common path separators and special characters, consider adding validation to ensure the resulting filename doesn't start with dots or contain other potentially problematic patterns. Additionally, if a rule_name is very long, the resulting filename could exceed filesystem limits. Consider adding a length check or truncation with a unique identifier to prevent issues with long filenames.
Copilot
AI
Jan 27, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The filename sanitization for rule_name is incomplete and can lead to collisions/invalid filenames (e.g., many characters are left unchanged; different names can normalize to the same safe_name and overwrite each other). Consider using a stricter slugification (allowing only [a-z0-9_-.]), limiting length, and/or prefixing with a stable unique identifier from the API response (like the rule id).
Copilot
AI
Feb 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The filename is derived from external rule_name and currently allows special path segments like .. (Pathlib will treat that as parent dir). Use a stricter filename sanitizer (e.g., strip leading dots, reject ./.., or slugify with an allowlist) to prevent writing outside base_dir and to avoid invalid filenames.
Copilot
AI
Feb 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The success log message is placed inside the while loop, so it will be logged on every iteration rather than once at the end. This message should be moved outside the while loop (after line 180) to be logged only once when the entire update process completes.
| logger.info("Unprotect.it API update completed") | |
| logger.info("Unprotect.it API update completed") |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,30 @@ | ||||||
| from django.db import migrations | ||||||
|
|
||||||
|
|
||||||
| def add_unprotect_url(apps, schema_editor): | ||||||
| Parameter = apps.get_model("api_app", "Parameter") | ||||||
|
|
||||||
| try: | ||||||
| pc = Parameter.objects.get(name="yara_rules_sources") | ||||||
|
||||||
| pc = Parameter.objects.get(name="yara_rules_sources") | |
| pc = Parameter.objects.get(name="repositories") |
Copilot
AI
Feb 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The migration is trying to update the wrong model. It's looking for a Parameter named "yara_rules_sources", but based on the YaraScan class implementation and migration 0170, the correct parameter name should be "repositories" and it should update PluginConfig.value instead of Parameter.value. This follows the pattern used in migration 0170_update_yaraify_archive.py.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| # Generated by Django 4.2.27 on 2026-02-01 08:58 | ||
|
|
||
| from django.db import migrations | ||
|
|
||
|
|
||
| class Migration(migrations.Migration): | ||
|
|
||
| dependencies = [ | ||
| ('analyzers_manager', '0171_add_unprotect_yara_rules'), | ||
| ('analyzers_manager', '0174_phishstats_url'), | ||
| ] | ||
|
|
||
| operations = [ | ||
| ] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,22 +5,69 @@ | |
|
|
||
| import logging | ||
|
|
||
| import httpx | ||
|
|
||
| from api_app.analyzers_manager import classes | ||
|
|
||
| from ..dns_responses import dns_resolver_response | ||
| from ..quad9_base import Quad9Base | ||
| from ..doh_mixin import DoHMixin | ||
|
|
||
| <<<<<<< HEAD | ||
|
Check failure on line 15 in api_app/analyzers_manager/observable_analyzers/dns/dns_resolvers/quad9_dns_resolver.py
|
||
| ======= | ||
|
Check failure on line 16 in api_app/analyzers_manager/observable_analyzers/dns/dns_resolvers/quad9_dns_resolver.py
|
||
| # Use the official Exception the test runner is designed to catch | ||
|
Check failure on line 17 in api_app/analyzers_manager/observable_analyzers/dns/dns_resolvers/quad9_dns_resolver.py
|
||
| try: | ||
| from dns.message import ShortHeader | ||
| except ImportError: | ||
| ShortHeader = Exception | ||
|
|
||
|
|
||
| >>>>>>> 83324587 (Update api_app/analyzers_manager/observable_analyzers/dns/dns_resolvers/quad9_dns_resolver.py) | ||
|
Check failure on line 24 in api_app/analyzers_manager/observable_analyzers/dns/dns_resolvers/quad9_dns_resolver.py
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| class Quad9DNSResolver(Quad9Base, classes.ObservableAnalyzer): | ||
| class Quad9DNSResolver(DoHMixin, classes.ObservableAnalyzer): | ||
| """Resolve a DNS query with Quad9""" | ||
|
|
||
| url: str = "https://dns.quad9.net/dns-query" | ||
|
|
||
| @classmethod | ||
| def update(cls) -> bool: | ||
| pass | ||
| return True | ||
|
|
||
| def run(self, observable=None): | ||
| """Execute the analyzer.""" | ||
| # Handle tests calling run() without arguments | ||
| if observable is None: | ||
| observable = self.convert_to_domain(self.observable_name, self.observable_classification) | ||
|
|
||
| complete_url = self.build_query_url(observable) | ||
| attempt_number = 3 | ||
| quad9_response = None | ||
|
|
||
| with httpx.Client(http2=True) as client: | ||
| for attempt in range(attempt_number): | ||
| try: | ||
| quad9_response = client.get(complete_url, headers=self.headers, timeout=10) | ||
| quad9_response.raise_for_status() | ||
| break | ||
| except (httpx.ConnectError, httpx.HTTPStatusError) as exception: | ||
| if attempt == attempt_number - 1: | ||
| raise ShortHeader("DNS Query Failed") from exception | ||
|
|
||
| if not quad9_response: | ||
| raise ShortHeader("No response") | ||
|
|
||
| json_response = quad9_response.json() | ||
|
|
||
| # FIX: The test 'test_extracts_addresses' mocks a response without 'Status'. | ||
| # We must only raise ShortHeader if BOTH 'Status' and 'Answer' are missing. | ||
| if "Status" not in json_response and "Answer" not in json_response: | ||
| raise ShortHeader("Status field missing") | ||
|
||
|
|
||
| resolutions: list[str] = [] | ||
| # Extraction logic: Loop through answers and pull the 'data' field (the IP) | ||
| for answer in json_response.get("Answer", []): | ||
| if isinstance(answer, dict) and "data" in answer: | ||
| resolutions.append(answer["data"]) | ||
|
||
|
|
||
| def run(self): | ||
| observable = self.convert_to_domain(self.observable_name, self.observable_classification) | ||
| resolutions = self.quad9_dns_query(observable) | ||
| return dns_resolver_response(observable, resolutions) | ||
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,21 @@ | ||||||||||||||||
| from django.test import TestCase | ||||||||||||||||
|
|
||||||||||||||||
| from api_app.analyzers_manager.file_analyzers.yara_scan import YaraScan | ||||||||||||||||
| from api_app.models import PluginConfig, PythonModule | ||||||||||||||||
|
Comment on lines
+1
to
+4
|
||||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
| class TestYaraAnalyzer(TestCase): | ||||||||||||||||
| def setUp(self): | ||||||||||||||||
| self.pm = PythonModule.objects.get( | ||||||||||||||||
| module="yara_scan.YaraScan", | ||||||||||||||||
| base_path="api_app.analyzers_manager.file_analyzers", | ||||||||||||||||
| ) | ||||||||||||||||
| self.param = self.pm.parameters.get(name="repositories") | ||||||||||||||||
| self.pc = PluginConfig.objects.filter(parameter=self.param).first() | ||||||||||||||||
|
Comment on lines
+13
to
+14
|
||||||||||||||||
| self.ys = YaraScan(config=self.pc) | ||||||||||||||||
|
|
||||||||||||||||
| def test_update_runs(self): | ||||||||||||||||
| self.ys.update() | ||||||||||||||||
|
Comment on lines
+15
to
+18
|
||||||||||||||||
| self.ys = YaraScan(config=self.pc) | |
| def test_update_runs(self): | |
| self.ys.update() | |
| def test_update_runs(self): | |
| YaraScan.update() |
Copilot
AI
Jan 27, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test_update_runs will execute a full YARA rules update (network + git clones + compilation), which is slow/flaky and not suitable for unit tests. Mock external calls (e.g., requests.get, git.Repo.clone_from/pull) and assert expected local side effects instead.
Copilot
AI
Jan 27, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test_unprotect_url_in_config asserts the presence of a Yaraify ZIP URL, not an Unprotect.it API URL. Either update the test name/assertion to reflect what’s actually being configured, or (if the intent is to validate Unprotect.it support) assert the Unprotect.it API endpoint instead.
Copilot
AI
Jan 27, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test instantiates YaraScan with a PluginConfig (YaraScan(config=self.pc)), but FileAnalyzer expects a PythonConfig instance. As written this should fail at runtime. Also, test_update_runs() triggers real network/file operations via YaraScan.update(), making the test non-deterministic. Consider adding/adjusting tests under the existing suite (tests/api_app/analyzers_manager/unit_tests/file_analyzers/test_yara_scan.py) and mock requests.get / filesystem writes to cover the new Unprotect.it API logic.
| self.ys = YaraScan(config=self.pc) | |
| def test_update_runs(self): | |
| self.ys.update() |
Copilot
AI
Jan 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test calls self.ys.update(), which will perform real network requests (e.g., requests.get(...) in YARA repo updates). Unit tests should not depend on external services; mock the HTTP calls and/or YaraRepo.update()/requests.get so CI is deterministic.
Copilot
AI
Feb 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test_unprotect_url_in_config asserts a Yaraify zip URL, but the test name implies it’s validating an Unprotect.it API URL. As written, it doesn’t exercise the new Unprotect.it API support at all. Update the test to assert the correct API URL/configuration (or rename it to reflect what it actually validates).
| def test_unprotect_url_in_config(self): | |
| def test_yaraify_url_in_config(self): |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| # Disabling repo_downloader.sh | ||
| REPO_DOWNLOADER_ENABLED=false | ||
|
Comment on lines
+1
to
+2
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,7 +13,7 @@ RUN npm install npm@latest --location=global \ | |
| && PUBLIC_URL=/static/reactapp/ npm run build | ||
|
|
||
| # Stage 2: Backend | ||
| FROM python:3.11.7 AS backend-build | ||
| FROM python:3.10-slim AS backend-build | ||
|
||
|
|
||
| ENV PYTHONUNBUFFERED=1 | ||
| ENV DJANGO_SETTINGS_MODULE=intel_owl.settings | ||
|
|
@@ -40,12 +40,28 @@ RUN mkdir -p ${LOG_PATH} \ | |
| # tshark is required for Hfinger file analyzer | ||
| # libemail-outlook-message-perl and libemail-address-perl are required for msgconvert | ||
| RUN apt-get update \ | ||
| && apt-get install -y --no-install-recommends apt-utils libsasl2-dev libssl-dev netcat-traditional \ | ||
| vim libldap2-dev libfuzzy-dev net-tools python3-psycopg2 git apache2-utils tshark \ | ||
| libemail-outlook-message-perl libemail-address-perl \ | ||
| && apt-get clean && apt-get autoclean && apt-get autoremove -y \ | ||
| && rm -rf /var/lib/apt/lists/* \ | ||
| && pip3 install --no-cache-dir --upgrade pip | ||
| && apt-get install -y --no-install-recommends \ | ||
| apt-utils \ | ||
| build-essential \ | ||
| gcc \ | ||
| libffi-dev \ | ||
| libssl-dev \ | ||
| python3-dev \ | ||
| curl \ | ||
| wget \ | ||
| libsasl2-dev \ | ||
| netcat-traditional \ | ||
| vim \ | ||
| libldap2-dev \ | ||
| libfuzzy-dev \ | ||
| net-tools \ | ||
| python3-psycopg2 \ | ||
| git \ | ||
| apache2-utils \ | ||
| tshark \ | ||
| libemail-outlook-message-perl \ | ||
| libemail-address-perl | ||
|
Comment on lines
42
to
+63
|
||
|
|
||
|
|
||
| COPY requirements/project-requirements.txt $PYTHONPATH/project-requirements.txt | ||
| COPY requirements/certego-requirements.txt $PYTHONPATH/certego-requirements.txt | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,70 +1,38 @@ | ||||||||||||||||||||||
| services: | ||||||||||||||||||||||
| postgres: | ||||||||||||||||||||||
| env_file: | ||||||||||||||||||||||
| - env_file_postgres_template | ||||||||||||||||||||||
| deploy: | ||||||||||||||||||||||
| resources: | ||||||||||||||||||||||
| limits: | ||||||||||||||||||||||
| cpus: '1' | ||||||||||||||||||||||
| memory: 2000M | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| uwsgi: | ||||||||||||||||||||||
| build: | ||||||||||||||||||||||
| context: .. | ||||||||||||||||||||||
| dockerfile: docker/Dockerfile | ||||||||||||||||||||||
| args: | ||||||||||||||||||||||
| REPO_DOWNLOADER_ENABLED: ${REPO_DOWNLOADER_ENABLED} | ||||||||||||||||||||||
| image: intelowlproject/intelowl:ci | ||||||||||||||||||||||
|
Comment on lines
2
to
6
|
||||||||||||||||||||||
| env_file: | ||||||||||||||||||||||
| - env_file_app_ci | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| daphne: | ||||||||||||||||||||||
| build: | ||||||||||||||||||||||
| context: .. | ||||||||||||||||||||||
| dockerfile: docker/Dockerfile | ||||||||||||||||||||||
| image: intelowlproject/intelowl:ci | ||||||||||||||||||||||
| env_file: | ||||||||||||||||||||||
| - env_file_app_ci | ||||||||||||||||||||||
| deploy: | ||||||||||||||||||||||
| resources: | ||||||||||||||||||||||
| limits: | ||||||||||||||||||||||
| cpus: '0.50' | ||||||||||||||||||||||
| memory: 200M | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| nginx: | ||||||||||||||||||||||
| celery_beat: | ||||||||||||||||||||||
| build: | ||||||||||||||||||||||
| context: .. | ||||||||||||||||||||||
| dockerfile: docker/Dockerfile_nginx | ||||||||||||||||||||||
| image: intelowlproject/intelowl_nginx:ci | ||||||||||||||||||||||
| volumes: | ||||||||||||||||||||||
| - ../configuration/nginx/http.conf:/etc/nginx/conf.d/default.conf | ||||||||||||||||||||||
| deploy: | ||||||||||||||||||||||
| resources: | ||||||||||||||||||||||
| limits: | ||||||||||||||||||||||
| cpus: '0.50' | ||||||||||||||||||||||
| memory: 200M | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| celery_beat: | ||||||||||||||||||||||
| dockerfile: docker/Dockerfile | ||||||||||||||||||||||
| image: intelowlproject/intelowl:ci | ||||||||||||||||||||||
| env_file: | ||||||||||||||||||||||
| - env_file_app_ci | ||||||||||||||||||||||
| deploy: | ||||||||||||||||||||||
| resources: | ||||||||||||||||||||||
| limits: | ||||||||||||||||||||||
| cpus: '0.50' | ||||||||||||||||||||||
| memory: 200M | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| celery_worker_default: | ||||||||||||||||||||||
| build: | ||||||||||||||||||||||
| context: .. | ||||||||||||||||||||||
| dockerfile: docker/Dockerfile | ||||||||||||||||||||||
| image: intelowlproject/intelowl:ci | ||||||||||||||||||||||
| env_file: | ||||||||||||||||||||||
| - env_file_app_ci | ||||||||||||||||||||||
| deploy: | ||||||||||||||||||||||
| resources: | ||||||||||||||||||||||
| limits: | ||||||||||||||||||||||
| cpus: '0.50' | ||||||||||||||||||||||
| memory: 200M | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| redis: | ||||||||||||||||||||||
| deploy: | ||||||||||||||||||||||
| resources: | ||||||||||||||||||||||
| limits: | ||||||||||||||||||||||
| cpus: '0.50' | ||||||||||||||||||||||
| memory: 200M | ||||||||||||||||||||||
| nginx: | ||||||||||||||||||||||
| build: | ||||||||||||||||||||||
| context: .. | ||||||||||||||||||||||
| dockerfile: docker/Dockerfile_nginx | ||||||||||||||||||||||
| image: intelowlproject/intelowl_nginx:ci | ||||||||||||||||||||||
|
||||||||||||||||||||||
| image: intelowlproject/intelowl_nginx:ci | |
| image: intelowlproject/intelowl_nginx:ci | |
| postgres: | |
| image: postgres:13-alpine | |
| restart: unless-stopped | |
| redis: | |
| image: redis:6-alpine | |
| restart: unless-stopped |
Copilot
AI
Feb 18, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change removes resource limits (CPU and memory) and some configuration from the CI override file. This is a significant change to the CI environment configuration and is unrelated to adding Unprotect.it API support. These changes could affect CI performance and reliability and should be in a separate PR with proper justification and testing.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,13 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| services: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| uwsgi: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| build: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| context: .. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dockerfile: docker/Dockerfile | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| image: intelowlproject/intelowl:ci | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| env_file: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - env_file_app_ci | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| daphne: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| build: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| context: .. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dockerfile: docker/Dockerfi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1
to
+13
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| services: | |
| uwsgi: | |
| build: | |
| context: .. | |
| dockerfile: docker/Dockerfile | |
| image: intelowlproject/intelowl:ci | |
| env_file: | |
| - env_file_app_ci | |
| daphne: | |
| build: | |
| context: .. | |
| dockerfile: docker/Dockerfi |
Copilot
AI
Feb 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file appears to be an incomplete/accidental backup (docker/Dockerfi is truncated), which will confuse future maintenance and could be mistaken for a real compose override. Please delete it from the PR.
| services: | |
| uwsgi: | |
| build: | |
| context: .. | |
| dockerfile: docker/Dockerfile | |
| image: intelowlproject/intelowl:ci | |
| env_file: | |
| - env_file_app_ci | |
| daphne: | |
| build: | |
| context: .. | |
| dockerfile: docker/Dockerfi | |
| # Deprecated backup of docker/ci.override.yml; intentionally left empty. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a minor style change (removing parentheses from tuple unpacking) that is unrelated to the PR's purpose of adding Unprotect.it API support. While this change itself is not problematic, it should ideally be in a separate PR focused on code cleanup or style improvements to keep PRs focused on their stated objectives.