diff --git a/.gitea/workflows/docker-build.yaml b/.gitea/workflows/docker-build.yaml index ad8a099..27271af 100644 --- a/.gitea/workflows/docker-build.yaml +++ b/.gitea/workflows/docker-build.yaml @@ -145,7 +145,7 @@ jobs: name: Проверить опубликованные образы needs: [build-and-push-backend, build-and-push-frontend] runs-on: ubuntu-latest - timeout-minutes: 20 + timeout-minutes: 35 env: BACKEND_REF: ${{ env.REGISTRY }}/${{ env.BACKEND_IMAGE }}@${{ needs.build-and-push-backend.outputs.digest }} FRONTEND_REF: ${{ env.REGISTRY }}/${{ env.FRONTEND_IMAGE }}@${{ needs.build-and-push-frontend.outputs.digest }} @@ -167,7 +167,7 @@ jobs: "${{ env.TRIVY_IMAGE }}" \ --env DOCKER_CONFIG=/workspace \ -- \ - image --scanners vuln --exit-code 1 --severity HIGH,CRITICAL --ignore-unfixed \ + image --timeout 15m --scanners vuln --exit-code 1 --severity HIGH,CRITICAL --ignore-unfixed \ "$BACKEND_REF" - name: Проверить frontend на HIGH и CRITICAL уязвимости @@ -177,7 +177,7 @@ jobs: "${{ env.TRIVY_IMAGE }}" \ --env DOCKER_CONFIG=/workspace \ -- \ - image --scanners vuln --exit-code 1 --severity HIGH,CRITICAL --ignore-unfixed \ + image --timeout 15m --scanners vuln --exit-code 1 --severity HIGH,CRITICAL --ignore-unfixed \ "$FRONTEND_REF" deploy-to-k8s: diff --git a/docs/INFRASTRUCTURE.md b/docs/INFRASTRUCTURE.md index c5da073..72bd7bd 100644 --- a/docs/INFRASTRUCTURE.md +++ b/docs/INFRASTRUCTURE.md @@ -375,7 +375,9 @@ Deployment-файлов запрещено. 4. Отдельный обязательный job сканирует опубликованные digests закреплённым Trivy `0.63.0` и блокирует deploy при исправимых `HIGH`/`CRITICAL` уязвимостях. Docker credentials для приватного registry копируются во временный Trivy-контейнер через Docker API; bind mount - домашнего каталога job-контейнера не используется. + домашнего каталога job-контейнера не используется. Для каждого scan задан таймаут `15m`, + чтобы загрузка vulnerability/Java DB и анализ Java-слоёв не прерывались стандартным + пятиминутным лимитом Trivy; общий лимит job составляет 35 минут. 5. Push в `main` выполняет проверки, сборку, публикацию и scan, но не меняет production. Deploy job запускается только вручную через `workflow_dispatch` и устанавливает фиксированный `kubectl v1.33.12` после SHA-256 проверки. Java Agent также имеет точную diff --git a/graphify-out/.graphify_learning.json b/graphify-out/.graphify_learning.json index bdbf2fb..762d716 100644 --- a/graphify-out/.graphify_learning.json +++ b/graphify-out/.graphify_learning.json @@ -1,27 +1,37 @@ { - "generated_at": "2026-07-29T21:00:52.911357+00:00", + "generated_at": "2026-07-29T21:47:12.291616+00:00", "nodes": { "_gitea_workflows_docker_build_backend_image_pipeline": { "code_fingerprint": "672f3effb2b85afa48bca601809662a5567dc0d57a24b224d4c7f1624899b222", "label": "Pipeline backend-образа", - "last": "2026-07-29T20:38:53.488440+00:00", + "last": "2026-07-29T21:27:26.637336+00:00", "provenance": [ + { + "date": "2026-07-29T21:27:26.637336+00:00", + "outcome": "useful", + "q": "Проверить опубликованные образы: backend Trivy HIGH/CRITICAL scan завершился exitcode 1" + }, { "date": "2026-07-29T20:38:53.488440+00:00", "outcome": "useful", "q": "The goal you specified requires a project to execute but there is no POM in this directory (/workspace)." } ], - "score": 0.999647225, + "score": 1.998587492, "source_file": ".gitea/workflows/docker-build.yaml", - "status": "tentative", - "uses": 1 + "status": "preferred", + "uses": 2 }, "_gitea_workflows_docker_build_build_and_push_docker_images": { "code_fingerprint": "672f3effb2b85afa48bca601809662a5567dc0d57a24b224d4c7f1624899b222", "label": "Workflow сборки и публикации Docker-образов", - "last": "2026-07-29T20:38:53.488440+00:00", + "last": "2026-07-29T21:27:26.637336+00:00", "provenance": [ + { + "date": "2026-07-29T21:27:26.637336+00:00", + "outcome": "useful", + "q": "Проверить опубликованные образы: backend Trivy HIGH/CRITICAL scan завершился exitcode 1" + }, { "date": "2026-07-29T20:38:53.488440+00:00", "outcome": "useful", @@ -43,10 +53,10 @@ "q": "теперь напиши мне инструкцию как это всё выыкатить на прод. у мня уже поднят на проде этот сервис со старой базой данных, но я могу её затереть. ci/cd тоже настроен, по сути я прямо сейчас могу залить это в ветку мейн и оно должно раскататься. каие есть подводные камни после изменений безопасности которые мы внесли?" } ], - "score": 3.996372989, + "score": 4.99308675, "source_file": ".gitea/workflows/docker-build.yaml", "status": "preferred", - "uses": 4 + "uses": 5 }, "_gitea_workflows_docker_build_deploy_to_k8s": { "code_fingerprint": "672f3effb2b85afa48bca601809662a5567dc0d57a24b224d4c7f1624899b222", @@ -59,7 +69,7 @@ "q": "сам можешь выполнить эти действия?" } ], - "score": 0.999226384, + "score": 0.998483979, "source_file": ".gitea/workflows/docker-build.yaml", "status": "tentative", "uses": 1 @@ -75,7 +85,7 @@ "q": "The goal you specified requires a project to execute but there is no POM in this directory (/workspace)." } ], - "score": 0.999647225, + "score": 0.998904507, "source_file": ".gitea/workflows/docker-build.yaml", "status": "tentative", "uses": 1 @@ -101,7 +111,7 @@ "q": "Почему RequireRoles связывает множество контроллеров, моделей и сервисов как cross-community bridge?" } ], - "score": 1.859406956, + "score": 1.858025454, "source_file": "backend/src/main/java/com/magistr/app/config/auth/AuthorizationInterceptor.java", "status": "preferred", "uses": 3 @@ -117,7 +127,7 @@ "q": "Какие подсистемы связывают исправления аутентификации, tenant-конфигурации, расписания и инфраструктуры?" } ], - "score": 0.660617324, + "score": 0.660126499, "source_file": "backend/src/main/java/com/magistr/app/config/auth/JwtTokenService.java", "status": "tentative", "uses": 1 @@ -133,7 +143,7 @@ "q": "Почему RequireRoles связывает множество контроллеров, моделей и сервисов как cross-community bridge?" } ], - "score": 0.555827846, + "score": 0.555414877, "source_file": "backend/src/main/java/com/magistr/app/config/auth/RequireRoles.java", "status": "tentative", "uses": 1 @@ -149,7 +159,7 @@ "q": "Как безопасно обновлять tenant DataSource без потери рабочего подключения?" } ], - "score": 0.676036488, + "score": 0.675534207, "source_file": "backend/src/main/java/com/magistr/app/config/DataInitializer.java", "status": "tentative", "uses": 1 @@ -165,7 +175,7 @@ "q": "проанализируй весь проект на баги и ошибки и дополни '/mnt/HDD/ProjectMagistr/magistr/BUG_REPORT.md'" } ], - "score": 0.642961786, + "score": 0.642484079, "source_file": "backend/src/main/java/com/magistr/app/config/tenant/ConfigMapUpdater.java", "status": "tentative", "uses": 1 @@ -181,7 +191,7 @@ "q": "Как безопасно заменить tenant DataSource без потери рабочего подключения?" } ], - "score": 0.675921865, + "score": 0.675419668, "source_file": "backend/src/main/java/com/magistr/app/config/tenant/TenantConfig.java", "status": "tentative", "uses": 1 @@ -207,7 +217,7 @@ "q": "проанализируй весь проект на баги и ошибки и дополни '/mnt/HDD/ProjectMagistr/magistr/BUG_REPORT.md'" } ], - "score": 1.994920139, + "score": 1.993437954, "source_file": "backend/src/main/java/com/magistr/app/config/tenant/TenantConfigWatcher.java", "status": "preferred", "uses": 3 @@ -233,7 +243,7 @@ "q": "Какие подсистемы связывают исправления аутентификации, tenant-конфигурации, расписания и инфраструктуры?" } ], - "score": 2.012575677, + "score": 2.011080374, "source_file": "backend/src/main/java/com/magistr/app/config/tenant/TenantRoutingDataSource.java", "status": "preferred", "uses": 3 @@ -249,7 +259,7 @@ "q": "Почему в выборе аудитории показаны корпус и этаж?" } ], - "score": 0.831090126, + "score": 0.830472643, "source_file": "backend/src/main/java/com/magistr/app/controller/ClassroomController.java", "status": "tentative", "uses": 1 @@ -265,7 +275,7 @@ "q": "Какие подсистемы связывают исправления аутентификации, tenant-конфигурации, расписания и инфраструктуры?" } ], - "score": 0.660617324, + "score": 0.660126499, "source_file": "backend/src/main/java/com/magistr/app/controller/DatabaseController.java", "status": "tentative", "uses": 1 @@ -286,7 +296,7 @@ "q": "Как безопасно заменить tenant DataSource без потери рабочего подключения?" } ], - "score": 1.351958353, + "score": 1.350953875, "source_file": "backend/src/main/java/com/magistr/app/controller/DatabaseController.java", "status": "preferred", "uses": 2 @@ -302,7 +312,7 @@ "q": "проанализируй весь проект на баги и ошибки и дополни '/mnt/HDD/ProjectMagistr/magistr/BUG_REPORT.md'" } ], - "score": 0.642961786, + "score": 0.642484079, "source_file": "backend/src/main/java/com/magistr/app/controller/GlobalExceptionHandler.java", "status": "tentative", "uses": 1 @@ -323,7 +333,7 @@ "q": "Какие подсистемы связывают исправления аутентификации, tenant-конфигурации, расписания и инфраструктуры?" } ], - "score": 1.490940058, + "score": 1.48983232, "source_file": "backend/src/main/java/com/magistr/app/controller/ScheduleController.java", "status": "preferred", "uses": 2 @@ -339,7 +349,7 @@ "q": "Как безопасно валидировать и сохранять точечные изменения расписания?" } ], - "score": 0.671192001, + "score": 0.670693319, "source_file": "backend/src/main/java/com/magistr/app/controller/ScheduleOverrideController.java", "status": "tentative", "uses": 1 @@ -360,7 +370,7 @@ "q": "проанализируй весь проект на баги и ошибки и дополни '/mnt/HDD/ProjectMagistr/magistr/BUG_REPORT.md'" } ], - "score": 1.318654271, + "score": 1.317674538, "source_file": "backend/src/main/java/com/magistr/app/controller/ScheduleRuleAdminController.java", "status": "preferred", "uses": 2 @@ -376,7 +386,7 @@ "q": "хотим поменять название сервиса, придумай что-то короткое одним словом подходящее по смыслу" } ], - "score": 0.850790945, + "score": 0.850158824, "source_file": "backend/src/main/java/com/magistr/app/model/AcademicCalendar.java", "status": "tentative", "uses": 1 @@ -392,7 +402,7 @@ "q": "Почему в выборе аудитории показаны корпус и этаж?" } ], - "score": 0.831090126, + "score": 0.830472643, "source_file": "backend/src/main/java/com/magistr/app/model/Classroom.java", "status": "tentative", "uses": 1 @@ -408,7 +418,7 @@ "q": "хотим поменять название сервиса, придумай что-то короткое одним словом подходящее по смыслу" } ], - "score": 0.850790945, + "score": 0.850158824, "source_file": "backend/src/main/java/com/magistr/app/model/Department.java", "status": "tentative", "uses": 1 @@ -429,7 +439,7 @@ "q": "Корректны ли inferred-связи вокруг ScheduleRule?" } ], - "score": 1.232140722, + "score": 1.231225267, "source_file": "backend/src/main/java/com/magistr/app/model/ScheduleRule.java", "status": "preferred", "uses": 2 @@ -445,7 +455,7 @@ "q": "Какие связи затрагивает полная валидация правил расписания в исправлении №7?" } ], - "score": 0.675692485, + "score": 0.675190459, "source_file": "backend/src/main/java/com/magistr/app/model/ScheduleRuleSlot.java", "status": "tentative", "uses": 1 @@ -466,7 +476,7 @@ "q": "в дополнительные фильры просмотра расписаний нужно добавить выбор семестра" } ], - "score": 1.681113679, + "score": 1.679864645, "source_file": "backend/src/main/java/com/magistr/app/model/Semester.java", "status": "preferred", "uses": 2 @@ -482,7 +492,7 @@ "q": "хотим поменять название сервиса, придумай что-то короткое одним словом подходящее по смыслу" } ], - "score": 0.850790945, + "score": 0.850158824, "source_file": "backend/src/main/java/com/magistr/app/model/StudentGroup.java", "status": "tentative", "uses": 1 @@ -498,7 +508,7 @@ "q": "Какие связи затрагивает полная валидация правил расписания в исправлении №7?" } ], - "score": 0.675692485, + "score": 0.675190459, "source_file": "backend/src/main/java/com/magistr/app/repository/SemesterRepository.java", "status": "tentative", "uses": 1 @@ -519,7 +529,7 @@ "q": "Как безопасно валидировать и сохранять точечные изменения расписания?" } ], - "score": 1.501514735, + "score": 1.50039914, "source_file": "backend/src/main/java/com/magistr/app/service/ScheduleQueryService.java", "status": "preferred", "uses": 2 @@ -535,7 +545,7 @@ "q": "Корректны ли inferred-связи вокруг ScheduleRule?" } ], - "score": 0.556448237, + "score": 0.556034807, "source_file": "backend/src/test/java/com/magistr/app/model/ScheduleRuleTest.java", "status": "tentative", "uses": 1 @@ -551,7 +561,7 @@ "q": "Какие подсистемы связывают исправления аутентификации, tenant-конфигурации, расписания и инфраструктуры?" } ], - "score": 0.660617324, + "score": 0.660126499, "source_file": "compose.yaml", "status": "tentative", "uses": 1 @@ -567,7 +577,7 @@ "q": "новая схема на проде на удалённом сервере создана через CREATE SCHEMA public. я проверил, давай дальше" } ], - "score": 0.99900881, + "score": 0.998266566, "source_file": "compose.yaml", "status": "tentative", "uses": 1 @@ -583,29 +593,34 @@ "q": "теперь напиши мне инструкцию как это всё выыкатить на прод. у мня уже поднят на проде этот сервис со старой базой данных, но я могу её затереть. ci/cd тоже настроен, по сути я прямо сейчас могу залить это в ветку мейн и оно должно раскататься. каие есть подводные камни после изменений безопасности которые мы внесли?" } ], - "score": 0.998490571, + "score": 0.997748712, "source_file": "docs/DATABASE.md", "status": "tentative", "uses": 1 }, "docs_infrastructure_gitea_actions_cicd": { - "code_fingerprint": "40b5d07ca2998f186f60fcab44ece5a5bf3ee2ad747acfbe1be3c29d3b7a00f5", + "code_fingerprint": "710cfffbe78ceeac834c0ad6e1c2107b1c55772a142c461fd9ef3787e9f97ace", "label": "CI/CD Gitea Actions в инфраструктуре", - "last": "2026-07-29T20:38:53.488440+00:00", + "last": "2026-07-29T21:27:26.637336+00:00", "provenance": [ + { + "date": "2026-07-29T21:27:26.637336+00:00", + "outcome": "useful", + "q": "Проверить опубликованные образы: backend Trivy HIGH/CRITICAL scan завершился exitcode 1" + }, { "date": "2026-07-29T20:38:53.488440+00:00", "outcome": "useful", "q": "The goal you specified requires a project to execute but there is no POM in this directory (/workspace)." } ], - "score": 0.999647225, + "score": 1.998587492, "source_file": "docs/INFRASTRUCTURE.md", - "status": "tentative", - "uses": 1 + "status": "preferred", + "uses": 2 }, "docs_infrastructure_jwt_secret_policy": { - "code_fingerprint": "40b5d07ca2998f186f60fcab44ece5a5bf3ee2ad747acfbe1be3c29d3b7a00f5", + "code_fingerprint": "710cfffbe78ceeac834c0ad6e1c2107b1c55772a142c461fd9ef3787e9f97ace", "label": "Политика JWT-секрета", "last": "2026-07-29T20:12:38.880629+00:00", "provenance": [ @@ -620,13 +635,13 @@ "q": "теперь напиши мне инструкцию как это всё выыкатить на прод. у мня уже поднят на проде этот сервис со старой базой данных, но я могу её затереть. ci/cd тоже настроен, по сути я прямо сейчас могу залить это в ветку мейн и оно должно раскататься. каие есть подводные камни после изменений безопасности которые мы внесли?" } ], - "score": 1.997716954, + "score": 1.996232691, "source_file": "docs/INFRASTRUCTURE.md", "status": "preferred", "uses": 2 }, "docs_infrastructure_kubernetes_production": { - "code_fingerprint": "40b5d07ca2998f186f60fcab44ece5a5bf3ee2ad747acfbe1be3c29d3b7a00f5", + "code_fingerprint": "710cfffbe78ceeac834c0ad6e1c2107b1c55772a142c461fd9ef3787e9f97ace", "label": "Production-инфраструктура Kubernetes", "last": "2026-07-29T20:12:38.880629+00:00", "provenance": [ @@ -646,13 +661,13 @@ "q": "теперь напиши мне инструкцию как это всё выыкатить на прод. у мня уже поднят на проде этот сервис со старой базой данных, но я могу её затереть. ci/cd тоже настроен, по сути я прямо сейчас могу залить это в ветку мейн и оно должно раскататься. каие есть подводные камни после изменений безопасности которые мы внесли?" } ], - "score": 2.996725764, + "score": 2.994499257, "source_file": "docs/INFRASTRUCTURE.md", "status": "preferred", "uses": 3 }, "docs_infrastructure_tenants_configmap": { - "code_fingerprint": "40b5d07ca2998f186f60fcab44ece5a5bf3ee2ad747acfbe1be3c29d3b7a00f5", + "code_fingerprint": "710cfffbe78ceeac834c0ad6e1c2107b1c55772a142c461fd9ef3787e9f97ace", "label": "Tenants ConfigMap", "last": "2026-07-29T19:26:44.188240+00:00", "provenance": [ @@ -662,10 +677,26 @@ "q": "теперь напиши мне инструкцию как это всё выыкатить на прод. у мня уже поднят на проде этот сервис со старой базой данных, но я могу её затереть. ci/cd тоже настроен, по сути я прямо сейчас могу залить это в ветку мейн и оно должно раскататься. каие есть подводные камни после изменений безопасности которые мы внесли?" } ], - "score": 0.998490571, + "score": 0.997748712, "source_file": "docs/INFRASTRUCTURE.md", "status": "tentative", "uses": 1 + }, + "springbootapplication": { + "code_fingerprint": "", + "label": "SpringBootApplication", + "last": "2026-07-29T21:27:26.637336+00:00", + "provenance": [ + { + "date": "2026-07-29T21:27:26.637336+00:00", + "outcome": "useful", + "q": "Проверить опубликованные образы: backend Trivy HIGH/CRITICAL scan завершился exitcode 1" + } + ], + "score": 0.999682985, + "source_file": "", + "status": "tentative", + "uses": 1 } }, "version": 1 diff --git a/graphify-out/memory/query_20260729_215022_проверить_backend_на_high_и_critical_уязвимости__c.md b/graphify-out/memory/query_20260729_215022_проверить_backend_на_high_и_critical_уязвимости__c.md new file mode 100644 index 0000000..0b6c77a --- /dev/null +++ b/graphify-out/memory/query_20260729_215022_проверить_backend_на_high_и_critical_уязвимости__c.md @@ -0,0 +1,25 @@ +--- +type: "query" +date: "2026-07-29T21:50:22.465033+00:00" +question: "Проверить backend на HIGH и CRITICAL уязвимости: context deadline exceeded после загрузки Trivy DB" +contributor: "graphify" +outcome: "useful" +source_nodes: ["Workflow сборки и публикации Docker-образов", "Pipeline backend-образа", "Pipeline frontend-образа", "CI/CD Gitea Actions в инфраструктуре"] +--- + +# Q: Проверить backend на HIGH и CRITICAL уязвимости: context deadline exceeded после загрузки Trivy DB + +## Answer + +Expanded from original query via graph vocab: [backend, build, cache, container, docker, gitea, pipeline, registry, workflow]. Первый traversal по cache попал в frontend cache и был отброшен; уточнённый traversal вывел Workflow сборки и публикации Docker-образов, Pipeline backend-образа и Pipeline frontend-образа. Прямой разбор CI-лога подтвердил: Trivy не сформировал vulnerability report и завершился по стандартному timeout 5m во время Java layer analysis после загрузки vulnerability/Java DB. В workflow обоим scan добавлен --timeout 15m, security-scan job увеличен до 35 минут; severity HIGH,CRITICAL, exit-code 1, ignore-unfixed, Java DB и digest pinning сохранены. Локальный Trivy 0.63.0 с новой командой завершился успешно: Alpine 0, app.jar 0, OpenTelemetry agent 0. Regression gates и YAML validation прошли. + +## Outcome + +- Signal: useful + +## Source Nodes + +- Workflow сборки и публикации Docker-образов +- Pipeline backend-образа +- Pipeline frontend-образа +- CI/CD Gitea Actions в инфраструктуре \ No newline at end of file diff --git a/graphify-out/reflections/LESSONS.md b/graphify-out/reflections/LESSONS.md index f600f4e..e2ad9ae 100644 --- a/graphify-out/reflections/LESSONS.md +++ b/graphify-out/reflections/LESSONS.md @@ -1,19 +1,21 @@ # Lessons -_Auto-generated by `graphify reflect` from 16 session memories in graphify-out/memory/. Deterministic; no LLM. Use for orientation — verify before relying, and revisit dead ends if the code has changed since._ +_Auto-generated by `graphify reflect` from 17 session memories in graphify-out/memory/. Deterministic; no LLM. Use for orientation — verify before relying, and revisit dead ends if the code has changed since._ ## Summary -- 15 useful · 1 dead ends · 0 corrected · 0 unmarked +- 16 useful · 1 dead ends · 0 corrected · 0 unmarked ## Lessons **Preferred sources** — corroborated by ≥2 useful results; start here. -- `Workflow сборки и публикации Docker-образов` (4× useful) +- `Workflow сборки и публикации Docker-образов` (5× useful) - `Production-инфраструктура Kubernetes` (3× useful) - `ScheduleGeneratorService` (3× useful) - `TenantRoutingDataSource` (3× useful) +- `CI/CD Gitea Actions в инфраструктуре` (2× useful) +- `Pipeline backend-образа` (2× useful) - `Политика JWT-секрета` (2× useful) - `TenantConfigWatcher` (3× useful) - `AuthorizationInterceptor` (3× useful) @@ -26,8 +28,7 @@ _Auto-generated by `graphify reflect` from 16 session memories in graphify-out/m **Tentative** — useful in fewer than 2 results; verify before relying. -- `CI/CD Gitea Actions в инфраструктуре` (1× useful) -- `Pipeline backend-образа` (1× useful) +- `SpringBootApplication` (1× useful) - `Pipeline frontend-образа` (1× useful) - `Job деплоя в Kubernetes` (1× useful) - `PostgreSQL-сервис Docker Compose` (1× useful) diff --git a/scripts/check-artifact-pinning.sh b/scripts/check-artifact-pinning.sh index a346165..7f2236e 100755 --- a/scripts/check-artifact-pinning.sh +++ b/scripts/check-artifact-pinning.sh @@ -69,6 +69,8 @@ require_count() { } check_workflow_gates() { + local security_timeout + require_file "$WORKFLOW" || return require_file "$CI_CONTAINER_SCRIPT" || return require_file "$CI_CONTAINER_TEST" || return @@ -77,8 +79,8 @@ check_workflow_gates() { "для обоих образов должна публиковаться SBOM attestation" require_count '^[[:space:]]+provenance:[[:space:]]+mode=max$' 2 \ "для обоих образов должна публиковаться provenance attestation" - require_count 'image --scanners vuln --exit-code 1 --severity HIGH,CRITICAL' 2 \ - "оба образа должны проходить блокирующее HIGH/CRITICAL-сканирование" + require_count 'image --timeout 15m --scanners vuln --exit-code 1 --severity HIGH,CRITICAL' 2 \ + "оба образа должны проходить блокирующее HIGH/CRITICAL-сканирование с достаточным таймаутом" require_count 'TRIVY_IMAGE: [^[:space:]]+@sha256:[0-9a-f]{64}$' 1 \ "образ Trivy должен быть закреплён digest" require_count 'MAVEN_IMAGE: [^[:space:]]+@sha256:[0-9a-f]{64}$' 1 \ @@ -92,6 +94,23 @@ check_workflow_gates() { require_count '--env DOCKER_CONFIG=/workspace' 2 \ "оба Trivy scan должны получать registry credentials через Docker API" + security_timeout=$(awk ' + $0 == " security-scan:" { + in_job = 1 + next + } + in_job && $0 ~ /^ [[:alnum:]_-]+:$/ { + exit + } + in_job && $1 == "timeout-minutes:" { + print $2 + exit + } + ' "$WORKFLOW") + if [[ "$security_timeout" != "35" ]]; then + fail "security-scan job должен иметь таймаут 35 минут" + fi + if grep -Fq '${{ github.workspace }}' "$WORKFLOW" \ || grep -Fq -- '-v "$HOME' "$WORKFLOW"; then fail "нельзя использовать пути job-контейнера в bind mount внешнего Docker daemon" diff --git a/scripts/test-artifact-pinning.sh b/scripts/test-artifact-pinning.sh index 6db1819..59b13dc 100755 --- a/scripts/test-artifact-pinning.sh +++ b/scripts/test-artifact-pinning.sh @@ -38,6 +38,8 @@ if PROJECT_ROOT="$FIXTURE_DIR" bash "$CHECK_SCRIPT" >/dev/null 2>&1; then fi cp "$ROOT_DIR/backend/Dockerfile" "$FIXTURE_DIR/backend/Dockerfile" +cp "$ROOT_DIR/.gitea/workflows/docker-build.yaml" \ + "$FIXTURE_DIR/.gitea/workflows/docker-build.yaml" sed -i '/RUN apk upgrade --no-cache/d' "$FIXTURE_DIR/backend/Dockerfile" if PROJECT_ROOT="$FIXTURE_DIR" bash "$CHECK_SCRIPT" >/dev/null 2>&1; then printf 'Ошибка теста: отсутствие Alpine security updates не было отклонено\n' >&2 @@ -45,6 +47,24 @@ if PROJECT_ROOT="$FIXTURE_DIR" bash "$CHECK_SCRIPT" >/dev/null 2>&1; then fi cp "$ROOT_DIR/backend/Dockerfile" "$FIXTURE_DIR/backend/Dockerfile" +cp "$ROOT_DIR/.gitea/workflows/docker-build.yaml" \ + "$FIXTURE_DIR/.gitea/workflows/docker-build.yaml" +sed -i '0,/image --timeout 15m --scanners vuln/{s/image --timeout 15m --scanners vuln/image --scanners vuln/;}' \ + "$FIXTURE_DIR/.gitea/workflows/docker-build.yaml" +if PROJECT_ROOT="$FIXTURE_DIR" bash "$CHECK_SCRIPT" >/dev/null 2>&1; then + printf 'Ошибка теста: недостаточный таймаут Trivy не был отклонён\n' >&2 + exit 1 +fi + +cp "$ROOT_DIR/.gitea/workflows/docker-build.yaml" \ + "$FIXTURE_DIR/.gitea/workflows/docker-build.yaml" +sed -i '0,/timeout-minutes: 35/s//timeout-minutes: 20/' \ + "$FIXTURE_DIR/.gitea/workflows/docker-build.yaml" +if PROJECT_ROOT="$FIXTURE_DIR" bash "$CHECK_SCRIPT" >/dev/null 2>&1; then + printf 'Ошибка теста: недостаточный таймаут security-scan job не был отклонён\n' >&2 + exit 1 +fi + cp "$ROOT_DIR/.gitea/workflows/docker-build.yaml" \ "$FIXTURE_DIR/.gitea/workflows/docker-build.yaml" sed -i "/gitea.event_name == 'workflow_dispatch'/d" \