Skip to content

Commit

Permalink
add support for two profiles
Browse files Browse the repository at this point in the history
  • Loading branch information
freekmurze committed Feb 17, 2018
1 parent 321b65b commit b2b8c62
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 59 deletions.
22 changes: 11 additions & 11 deletions config/csp.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,24 @@
/*
* A csp profile will determine which csp headers will be set.
*/
'profile' => \Spatie\Csp\Profiles\Basic::class,
'profile' => '',

/*
* Headers will only be added if this setting is enabled
* This profile which will be put in report only mode. This is great for testing out
* a new profile or changes to existing csp policy without breaking anyting.
*/
'enabled' => env('CSP_ENABLED', true),
'report_only_profile' => \Spatie\Csp\Profiles\Basic::class,

/*
* All violations against the csp policy will be report to this url.
* A great server you could use for this is https://report-uri.com/
* Headers will only be added if this setting is enabled
*/
'report_uri' => env('CSP_REPORT_URI', ''),
'enabled' => env('CSP_ENABLED', true),

/*
* To test your policy you can turn on the report only mode.
* The policy will not be enforced by the browser, but any violations
* are reported to the given uri
* All violations against the csp policy will be reported to this url.
* A great service you could use for this is https://report-uri.com/
*
* You can override this setting by calling `reportTo` on your profile.
*/
'report_only' => env('CSP_ONLY_REPORT', false),

'report_uri' => env('CSP_REPORT_URI', ''),
];
34 changes: 22 additions & 12 deletions src/AddCspHeaders.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,42 @@

use Closure;
use Illuminate\Http\Request;
use Spatie\Csp\Exceptions\InvalidCspProfile;
use Spatie\Csp\Profiles\Profile;
use Illuminate\Support\Collection;

class AddCspHeaders
{
public function handle(Request $request, Closure $next)
{
$response = $next($request);

$profile = $this->getProfile();

if ($profile->shouldBeApplied($request, $response)) {
$profile->applyTo($response);
}
$this
->getProfiles()
->filter->shouldBeApplied($request, $response)
->each->applyTo($response);

return $response;
}

protected function getProfile(): Profile
protected function getProfiles(): Collection
{
$profile = app(Profile::class);
$profiles = collect();

$profileClass = config('csp.profile');

if (! empty($profileClass)) {
$profiles->push(ProfileFactory::create($profileClass));
}

$reportOnlyProfileClass = config('csp.report_only_profile');

if (! empty($reportOnlyProfileClass)) {
$profile = ProfileFactory::create($reportOnlyProfileClass);

$profile->reportOnly();

if (!is_a($profile, Profile::class, true)) {
throw InvalidCspProfile::create($profile);
$profiles->push($profile);
}

return $profile;
return $profiles;
}
}
17 changes: 0 additions & 17 deletions src/CspServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
namespace Spatie\Csp;

use Illuminate\Support\ServiceProvider;
use Spatie\Csp\Profiles\Profile;

class CspServiceProvider extends ServiceProvider
{
Expand All @@ -14,22 +13,6 @@ public function boot()
__DIR__.'/../config/csp.php' => config_path('csp.php'),
], 'config');
}

$this->app->bind(Profile::class, function () {
$profileClass = config('csp.profile');

$profile = app($profileClass);

if (! empty(config('csp.report_uri'))) {
$profile->reportTo(config('csp.report_uri'));
}

if (config('csp.report_only')) {
$profile->reportOnly();
}

return $profile;
});
}

public function register()
Expand Down
24 changes: 24 additions & 0 deletions src/ProfileFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Spatie\Csp;

use Spatie\Csp\Exceptions\InvalidCspProfile;
use Spatie\Csp\Profiles\Profile;

class ProfileFactory
{
public static function create(string $className): Profile
{
$profile = app($className);

if (!is_a($profile, Profile::class, true)) {
throw InvalidCspProfile::create($profile);
}

if (! empty(config('csp.report_uri'))) {
$profile->reportTo(config('csp.report_uri'));
}

return $profile;
}
}
48 changes: 29 additions & 19 deletions tests/AddCspHeadersTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Illuminate\Support\Facades\Route;
use Spatie\Csp\AddCspHeaders;
use Spatie\Csp\Exceptions\InvalidCspProfile;
use Spatie\Csp\Profiles\Basic;
use Symfony\Component\HttpFoundation\HeaderBag;

class AddCspHeadersTest extends TestCase
Expand All @@ -19,32 +20,40 @@ public function setUp()
}

/** @test */
public function it_can_set_the_basic_csp_headers()
public function the_default_configuration_will_only_set_report_only_headers()
{
$headers = $this->getResponseHeaders();

$this->assertContains("default-src 'self';", $headers->get('Content-Security-Policy'));
$this->assertNotNull($headers->get('Content-Security-Policy-Report-Only'));
$this->assertContains("default-src 'self';", $headers->get('Content-Security-Policy-Report-Only'));

$this->assertNull($headers->get('Content-Security-Policy'));
}

/** @test */
public function it_wont_set_any_headers_if_not_enabled_in_the_config()
public function it_can_set_the_basic_csp_headers()
{
config(['csp.enabled' => false]);
config([
'csp.profile' => Basic::class,
'csp.report_only_profile' => '',
]);

$headers = $this->getResponseHeaders();

$this->assertNull($headers->get('Content-Security-Policy'));
$this->assertContains("default-src 'self';", $headers->get('Content-Security-Policy'));
}

/** @test */
public function it_can_be_set_in_report_only_mode_via_the_config()
public function it_wont_set_any_headers_if_not_enabled_in_the_config()
{
config(['csp.report_only' => true]);
config([
'csp.profile' => Basic::class,
'csp.report_only_profile' => '',
'csp.enabled' => false,
]);

$headers = $this->getResponseHeaders();

$this->assertNotNull($headers->get('Content-Security-Policy-Report-Only'));

$this->assertNull($headers->get('Content-Security-Policy'));
}

Expand All @@ -55,9 +64,17 @@ public function a_report_uri_can_be_set_in_the_config()

$headers = $this->getResponseHeaders();

$this
->assertCspHeaderContains($headers, 'report-uri https://report-uri.com;')
->assertCspHeaderContains($headers, 'report-to {"url":"https:\/\/report-uri.com","group-name":"Basic","max-age":18144000};');
$reportOnlyHeaderContent = $headers->get('Content-Security-Policy-Report-Only');

$this->assertContains(
'report-uri https://report-uri.com',
$reportOnlyHeaderContent
);

$this->assertContains(
'report-to {"url":"https:\/\/report-uri.com","group-name":"Basic","max-age":18144000};',
$reportOnlyHeaderContent
);
}

/** @test */
Expand All @@ -74,13 +91,6 @@ public function using_an_invalid_profile_class_will_throw_an_exception()
$this->getResponseHeaders();
}

protected function assertCspHeaderContains(HeaderBag $headerBag, string $needle): self
{
$this->assertContains($needle, $headerBag->get('Content-Security-Policy'));

return $this;
}

protected function getResponseHeaders(): HeaderBag
{
return $this
Expand Down

0 comments on commit b2b8c62

Please sign in to comment.