Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions config/module.config.php
Original file line number Diff line number Diff line change
Expand Up @@ -1231,6 +1231,57 @@
],
],
],

'risk_sources' => [
'type' => 'segment',
'options' => [
'route' => 'risk-sources[/:id]',
'constraints' => [
'id' => '[0-9]+',
],
'defaults' => [
'controller' => PipeSpec::class,
'middleware' => new PipeSpec(
AnrValidationMiddleware::class,
Controller\ApiAnrRiskSourcesController::class,
),
],
],
],

'interested_parties' => [
'type' => 'segment',
'options' => [
'route' => 'interested-parties[/:id]',
'constraints' => [
'id' => '[0-9]+',
],
'defaults' => [
'controller' => PipeSpec::class,
'middleware' => new PipeSpec(
AnrValidationMiddleware::class,
Controller\ApiAnrInterestedPartiesController::class,
),
],
],
],

'reassessment_triggers' => [
'type' => 'segment',
'options' => [
'route' => 'reassessment-triggers[/:id]',
'constraints' => [
'id' => '[0-9]+',
],
'defaults' => [
'controller' => PipeSpec::class,
'middleware' => new PipeSpec(
AnrValidationMiddleware::class,
Controller\ApiAnrReassessmentTriggersController::class,
),
],
],
],
],
],
'monarc_api_doc_models' => [
Expand Down Expand Up @@ -1401,6 +1452,9 @@
Controller\ApiConfigController::class => AutowireFactory::class,
Controller\ApiClientsController::class => AutowireFactory::class,
Controller\ApiCoreReferentialsController::class => AutowireFactory::class,
Controller\ApiAnrRiskSourcesController::class => AutowireFactory::class,
Controller\ApiAnrInterestedPartiesController::class => AutowireFactory::class,
Controller\ApiAnrReassessmentTriggersController::class => AutowireFactory::class,
Controller\ApiUserPasswordController::class => AutowireFactory::class,
Controller\ApiUserTwoFAController::class => AutowireFactory::class,
Controller\ApiUserRecoveryCodesController::class => AutowireFactory::class,
Expand Down Expand Up @@ -1509,6 +1563,9 @@
Table\OperationalRiskScaleTypeTable::class => ClientEntityManagerFactory::class,
Table\OperationalRiskScaleCommentTable::class => ClientEntityManagerFactory::class,
Table\OperationalInstanceRiskScaleTable::class => ClientEntityManagerFactory::class,
Table\RiskSourceTable::class => ClientEntityManagerFactory::class,
Table\InterestedPartyTable::class => ClientEntityManagerFactory::class,
Table\ReassessmentTriggerTable::class => ClientEntityManagerFactory::class,
Table\RecommendationTable::class => ClientEntityManagerFactory::class,
Table\RecommendationHistoryTable::class => ClientEntityManagerFactory::class,
Table\RecommendationRiskTable::class => ClientEntityManagerFactory::class,
Expand Down Expand Up @@ -1593,6 +1650,9 @@
Service\SoaService::class => AutowireFactory::class,
Service\SoaScaleCommentService::class => AutowireFactory::class,
Service\SystemMessageService::class => AutowireFactory::class,
Service\RiskSourceService::class => AutowireFactory::class,
Service\InterestedPartyService::class => AutowireFactory::class,
Service\ReassessmentTriggerService::class => AutowireFactory::class,
Stats\Service\StatsAnrService::class => ReflectionBasedAbstractFactory::class,
Stats\Service\StatsSettingsService::class => AutowireFactory::class,
CronTask\Service\CronTaskService::class => AutowireFactory::class,
Expand All @@ -1603,6 +1663,7 @@
/* Import services. */
Import\Service\ObjectImportService::class => AutowireFactory::class,
Import\Service\InstanceImportService::class => AutowireFactory::class,
Import\Processor\RiskSourceImportProcessor::class => AutowireFactory::class,

// Helpers
Import\Helper\ImportCacheHelper::class => AutowireFactory::class,
Expand Down Expand Up @@ -1844,6 +1905,9 @@
'monarc_api_guides_items',
'monarc_api_models',
'monarc_api_referentials',
'monarc_api_global_client_anr/risk_sources',
'monarc_api_global_client_anr/interested_parties',
'monarc_api_global_client_anr/reassessment_triggers',
'monarc_api_client',
'monarc_api_global_client_anr/carto_risks',
'monarc_api_global_client_anr/risk_owners',
Expand All @@ -1858,6 +1922,9 @@
'monarc_api_doc_models',
'monarc_api_models',
'monarc_api_referentials',
'monarc_api_global_client_anr/risk_sources',
'monarc_api_global_client_anr/interested_parties',
'monarc_api_global_client_anr/reassessment_triggers',
'monarc_api_admin_users_roles',
'monarc_api_global_client_anr/anr_instance_metadata_field',
'monarc_api_global_client_anr/instance_metadata',
Expand Down
67 changes: 67 additions & 0 deletions migrations/db/20260505100000_add_risk_sources.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php declare(strict_types=1);
/**
* @link https://github.com/monarc-project for the canonical source repository
* @copyright Copyright (c) 2016-2026 Luxembourg House of Cybersecurity LHC.lu - Licensed under GNU Affero GPL v3
* @license MONARC is licensed under GNU Affero General Public License version 3
*/

use Phinx\Migration\AbstractMigration;

class AddRiskSources extends AbstractMigration
{
public function up(): void
{
$this->execute(
'CREATE TABLE `risk_sources` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`anr_id` int(11) unsigned NOT NULL,
`label` varchar(255) NOT NULL,
`is_default` tinyint(1) NOT NULL DEFAULT 0,
`is_active` tinyint(1) NOT NULL DEFAULT 1,
`creator` varchar(255) DEFAULT NULL,
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
`updater` varchar(255) DEFAULT NULL,
`updated_at` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `risk_sources_anr_id_indx` (`anr_id`),
KEY `risk_sources_anr_id_is_active_indx` (`anr_id`, `is_active`),
UNIQUE `risk_sources_anr_id_label_unq` (`anr_id`, `label`),
FOREIGN KEY (`anr_id`) REFERENCES `anrs` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci'
);

$anrIds = $this->fetchAll('SELECT id FROM anrs');
foreach ($anrIds as $anr) {
$anrId = $anr['id'];
$this->execute(
"INSERT IGNORE INTO `risk_sources` (`anr_id`, `label`, `is_default`, `is_active`, `creator`, `created_at`) VALUES
({$anrId}, 'External attacker', 1, 1, 'System', NOW()),
({$anrId}, 'Internal malicious user', 1, 1, 'System', NOW()),
({$anrId}, 'Internal accidental user', 1, 1, 'System', NOW()),
({$anrId}, 'Supplier / third party', 1, 1, 'System', NOW()),
({$anrId}, 'System failure', 1, 1, 'System', NOW()),
({$anrId}, 'Software defect', 1, 1, 'System', NOW()),
({$anrId}, 'Natural event', 1, 1, 'System', NOW()),
({$anrId}, 'Organizational or process weakness', 1, 1, 'System', NOW()),
({$anrId}, 'Other', 1, 1, 'System', NOW());"
);
}

$this->table('instances_risks')
->addColumn('risk_source_id', 'integer', ['null' => true, 'signed' => false, 'after' => 'asset_id'])
->addIndex(['risk_source_id'], ['name' => 'risk_source_id'])
->addForeignKey('risk_source_id', 'risk_sources', 'id', ['delete' => 'SET_NULL', 'update' => 'RESTRICT'])
->update();
}

public function down(): void
{
$this->table('instances_risks')
->dropForeignKey('risk_source_id')
->removeIndexByName('risk_source_id')
->removeColumn('risk_source_id')
->update();

$this->table('risk_sources')->drop()->save();
}
}
40 changes: 40 additions & 0 deletions migrations/db/20260511101000_add_anr_reassessment_triggers.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php declare(strict_types=1);
/**
* @link https://github.com/monarc-project for the canonical source repository
* @copyright Copyright (c) 2016-2026 Luxembourg House of Cybersecurity LHC.lu - Licensed under GNU Affero GPL v3
* @license MONARC is licensed under GNU Affero General Public License version 3
*/

use Phinx\Migration\AbstractMigration;

class AddAnrReassessmentTriggers extends AbstractMigration
{
public function up(): void
{
$this->execute(
'CREATE TABLE IF NOT EXISTS `anr_reassessment_triggers` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`anr_id` int(11) unsigned NOT NULL,
`trigger_type` varchar(255) DEFAULT "",
`description` text NOT NULL,
`is_active` tinyint(1) NOT NULL DEFAULT 1,
`position` int(11) NOT NULL DEFAULT 0,
`creator` varchar(255) DEFAULT NULL,
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
`updater` varchar(255) DEFAULT NULL,
`updated_at` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `anr_reassessment_triggers_anr_id_indx` (`anr_id`),
KEY `anr_reassessment_triggers_anr_id_trigger_type_indx` (`anr_id`, `trigger_type`),
KEY `anr_reassessment_triggers_anr_id_position_indx` (`anr_id`, `position`),
CONSTRAINT `fk_anr_reassessment_triggers_anr`
FOREIGN KEY (`anr_id`) REFERENCES `anrs` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;'
);
}

public function down(): void
{
$this->table('anr_reassessment_triggers')->drop()->save();
}
}
35 changes: 35 additions & 0 deletions migrations/db/20260515101000_add_risk_review_metadata.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php declare(strict_types=1);
/**
* @link https://github.com/monarc-project for the canonical source repository
* @copyright Copyright (c) 2016-2026 Luxembourg House of Cybersecurity LHC.lu - Licensed under GNU Affero GPL v3
* @license MONARC is licensed under GNU Affero General Public License version 3
*/

use Phinx\Migration\AbstractMigration;

class AddRiskReviewMetadata extends AbstractMigration
{
public function up(): void
{
$this->table('instances_risks')
->addColumn('last_review_date', 'date', ['null' => true, 'after' => 'comment_after'])
->addColumn('review_frequency', 'string', ['limit' => 50, 'null' => true, 'after' => 'last_review_date'])
->update();

$this->table('anr_reassessment_triggers')
->addColumn('monitoring_approach', 'text', ['null' => true, 'after' => 'description'])
->update();
}

public function down(): void
{
$this->table('instances_risks')
->removeColumn('review_frequency')
->removeColumn('last_review_date')
->update();

$this->table('anr_reassessment_triggers')
->removeColumn('monitoring_approach')
->update();
}
}
59 changes: 59 additions & 0 deletions migrations/db/20260519101000_add_residual_risk_acceptance.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php declare(strict_types=1);
/**
* @link https://github.com/monarc-project for the canonical source repository
* @copyright Copyright (c) 2016-2026 Luxembourg House of Cybersecurity LHC.lu - Licensed under GNU Affero GPL v3
* @license MONARC is licensed under GNU Affero General Public License version 3
*/

use Phinx\Migration\AbstractMigration;

class AddResidualRiskAcceptance extends AbstractMigration
{
public function up(): void
{
$this->table('instances_risks')
->addColumn('residual_risk_decision', 'string', ['limit' => 20, 'null' => true, 'after' => 'review_frequency'])
->addColumn(
'residual_risk_approved_by',
'string',
['limit' => 255, 'null' => true, 'after' => 'residual_risk_decision']
)
->addColumn('residual_risk_approved_at', 'date', ['null' => true, 'after' => 'residual_risk_approved_by'])
->addColumn('residual_risk_justification', 'text', ['null' => true, 'after' => 'residual_risk_approved_at'])
->update();

$this->table('instances_risks_op')
->addColumn('last_review_date', 'date', ['null' => true, 'after' => 'mitigation'])
->addColumn('review_frequency', 'string', ['limit' => 50, 'null' => true, 'after' => 'last_review_date'])
->addColumn('residual_risk_decision', 'string', ['limit' => 20, 'null' => true, 'after' => 'review_frequency'])
->addColumn('residual_risk_approved_by', 'string', ['limit' => 255, 'null' => true, 'after' => 'residual_risk_decision'])
->addColumn('residual_risk_approved_at', 'date', ['null' => true, 'after' => 'residual_risk_approved_by'])
->addColumn('residual_risk_justification', 'text', ['null' => true, 'after' => 'residual_risk_approved_at'])
->addColumn('risk_source_id', 'integer', ['null' => true, 'signed' => false, 'after' => 'object_id'])
->addIndex(['risk_source_id'], ['name' => 'risk_source_id'])
->addForeignKey('risk_source_id', 'risk_sources', 'id', ['delete' => 'SET_NULL', 'update' => 'RESTRICT'])
->update();
}

public function down(): void
{
$this->table('instances_risks')
->removeColumn('residual_risk_justification')
->removeColumn('residual_risk_approved_at')
->removeColumn('residual_risk_approved_by')
->removeColumn('residual_risk_decision')
->update();

$this->table('instances_risks_op')
->removeColumn('residual_risk_justification')
->removeColumn('residual_risk_approved_at')
->removeColumn('residual_risk_approved_by')
->removeColumn('residual_risk_decision')
->removeColumn('review_frequency')
->removeColumn('last_review_date')
->dropForeignKey('risk_source_id')
->removeIndexByName('risk_source_id')
->removeColumn('risk_source_id')
->update();
}
}
33 changes: 33 additions & 0 deletions migrations/db/20260522101000_add_interested_parties.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php declare(strict_types=1);
/**
* @link https://github.com/monarc-project for the canonical source repository
* @copyright Copyright (c) 2016-2026 Luxembourg House of Cybersecurity LHC.lu - Licensed under GNU Affero GPL v3
* @license MONARC is licensed under GNU Affero General Public License version 3
*/

use Phinx\Migration\AbstractMigration;

class AddInterestedParties extends AbstractMigration
{
public function up(): void
{
$this->table('anr_interested_parties')
->addColumn('anr_id', 'integer', ['null' => false, 'signed' => false])
->addColumn('stakeholder', 'string', ['limit' => 255, 'null' => false])
->addColumn('requirement', 'text', ['null' => false])
->addColumn('position', 'integer', ['default' => 0, 'signed' => false])
->addColumn('creator', 'string', ['limit' => 255, 'null' => true])
->addColumn('created_at', 'datetime', ['null' => true])
->addColumn('updater', 'string', ['limit' => 255, 'null' => true])
->addColumn('updated_at', 'datetime', ['null' => true])
->addIndex(['anr_id'], ['name' => 'idx_anr_id'])
->addIndex(['anr_id', 'position'], ['name' => 'anr_interested_parties_anr_id_position_indx'])
->addForeignKey('anr_id', 'anrs', 'id', ['delete' => 'CASCADE', 'update' => 'RESTRICT'])
->create();
}

public function down(): void
{
$this->table('anr_interested_parties')->drop()->save();
}
}
8 changes: 8 additions & 0 deletions src/Controller/ApiAnrInstancesRisksController.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ public function update($id, $data)

return $this->getPreparedJsonResponse([
'id' => $instanceRisk->getId(),
'riskSourceId' => $instanceRisk->getRiskSource()?->getId(),
'riskSourceLabel' => $instanceRisk->getRiskSource()?->getLabel() ?? '',
'lastReviewDate' => $instanceRisk->getLastReviewDate()?->format('Y-m-d'),
'reviewFrequency' => $instanceRisk->getReviewFrequency(),
'residualRiskDecision' => $instanceRisk->getResidualRiskDecision(),
'residualRiskApprovedBy' => $instanceRisk->getResidualRiskApprovedBy(),
'residualRiskApprovedAt' => $instanceRisk->getResidualRiskApprovedAt()?->format('Y-m-d'),
'residualRiskJustification' => $instanceRisk->getResidualRiskJustification(),
'threatRate' => $instanceRisk->getThreatRate(),
'vulnerabilityRate' => $instanceRisk->getVulnerabilityRate(),
'reductionAmount' => $instanceRisk->getReductionAmount(),
Expand Down
8 changes: 8 additions & 0 deletions src/Controller/ApiAnrInstancesRisksOpController.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,14 @@ public function update($id, $data)
'cacheBrutRisk' => $instanceRiskOp->getCacheBrutRisk(),
'cacheNetRisk' => $instanceRiskOp->getCacheNetRisk(),
'cacheTargetedRisk' => $instanceRiskOp->getCacheTargetedRisk(),
'riskSourceId' => $instanceRiskOp->getRiskSource()?->getId(),
'riskSourceLabel' => $instanceRiskOp->getRiskSource()?->getLabel() ?? '',
'lastReviewDate' => $instanceRiskOp->getLastReviewDate()?->format('Y-m-d'),
'reviewFrequency' => $instanceRiskOp->getReviewFrequency(),
'residualRiskDecision' => $instanceRiskOp->getResidualRiskDecision(),
'residualRiskApprovedBy' => $instanceRiskOp->getResidualRiskApprovedBy(),
'residualRiskApprovedAt' => $instanceRiskOp->getResidualRiskApprovedAt()?->format('Y-m-d'),
'residualRiskJustification' => $instanceRiskOp->getResidualRiskJustification(),
]);
}
/**
Expand Down
Loading
Loading