CodeIgniter4でCSPのレポートを取得する

設定

diff --git a/app/Config/App.php b/app/Config/App.php
index 1a5e562dd..03e8eb649 100644
--- a/app/Config/App.php
+++ b/app/Config/App.php
@@ -461,5 +461,5 @@ class App extends BaseConfig
      *
      * @var bool
      */
-    public $CSPEnabled = false;
+    public $CSPEnabled = true;
 }
diff --git a/app/Config/ContentSecurityPolicy.php b/app/Config/ContentSecurityPolicy.php
index aa18ba9f1..3d863a634 100644
--- a/app/Config/ContentSecurityPolicy.php
+++ b/app/Config/ContentSecurityPolicy.php
@@ -32,7 +32,7 @@ class ContentSecurityPolicy extends BaseConfig
      *
      * @var string|null
      */
-    public $reportURI;
+    public $reportURI = '/csp-report';

     /**
      * Instructs user agents to rewrite URL schemes, changing
diff --git a/app/Config/Routes.php b/app/Config/Routes.php
index ff2ac645c..9d0907edc 100644
--- a/app/Config/Routes.php
+++ b/app/Config/Routes.php
@@ -37,6 +37,8 @@ $routes->set404Override();
 // route since we don't have to scan directories.
 $routes->get('/', 'Home::index');

+$routes->post('csp-report', 'CspReport::index');
+
 /*
  * --------------------------------------------------------------------
  * Additional Routing

コントローラ

<?php

namespace App\Controllers;

use CodeIgniter\I18n\Time;
use stdClass;

class CspReport extends BaseController
{
    private string $logfile = WRITEPATH . 'logs/csp-report.log';

    public function index()
    {
        $log = $this->createLogEntry();

        $this->addRequestHeaders($log);
        $this->addCspReport($log);
        $this->writeToLogfile($log);

        return $this->response->setStatusCode(204);
    }

    private function createLogEntry(): stdClass
    {
        $log = new stdClass();

        $log->date = Time::now()->format('Y-m-d H:i:s');

        return $log;
    }

    private function addRequestHeaders(stdClass $log): void
    {
        foreach ($this->request->headers() as $name => $value) {
            $log->headers[$name] = (string) $value;
        }
    }

    private function addCspReport(stdClass $log): void
    {
        /** @var stdClass|null $report */
        $report = $this->request->getJSON();

        if ($report !== null && json_last_error() === JSON_ERROR_NONE) {
            $log->{'csp-report'} = $report->{'csp-report'};
        }
    }

    private function writeToLogfile(stdClass $log): void
    {
        /** @var string $json */
        $json = json_encode($log, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);

        file_put_contents($this->logfile, $json . "\n", LOCK_EX | FILE_APPEND);
    }
}

参考

Date: 2022/08/17

Tags: codeigniter, codeigniter4, csp, logging