Skip to content

Commit 7c0b8e1

Browse files
authored
Merge pull request #29 from igorhrcek/issue-3
Issue 3
2 parents 201d1de + 924030d commit 7c0b8e1

8 files changed

+129
-2
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
.env
12
vendor/
23
.idea/
34
.phpunit.result.cache

src/RuleContent.php

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
class RuleContent {
66

7-
87
public array $content;
98
public array $templateVars;
109

src/SecureCommand.php

+33
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use WP_CLI;
66
use WP_CLI_Command;
7+
use WP_CLI_Secure\SubCommands\AddSecurityHeaders;
78
use WP_CLI_Secure\SubCommands\BlockAccessToCustomSensitiveFiles;
89
use WP_CLI_Secure\SubCommands\BlockAccessToHtaccess;
910
use WP_CLI_Secure\SubCommands\BlockAccessToSensitiveDirectories;
@@ -282,6 +283,38 @@ public function block_author_scanning($args, $assoc_args) : void {
282283
(new BlockAuthorScanning($assoc_args))->output();
283284
}
284285

286+
/**
287+
* Set Security Headers.
288+
*
289+
* ## OPTIONS
290+
*
291+
* [--remove]
292+
* : Removes the rule from .htaccess or nginx.conf.
293+
*
294+
* [--headers]
295+
* : Custom comma separated header list to add.
296+
*
297+
* [--output]
298+
* : Use this option to display the actual code that you can manually copy and paste into some other file
299+
*
300+
* [--headers=<headers>]
301+
* : List of headers you want to be added.
302+
*
303+
* [--server=<server>]
304+
* : Set a server type. Possible options are "apache" and "nginx". Default is "apache" and all rules are stored in
305+
* .htaccess file
306+
*
307+
* ## EXAMPLES
308+
*
309+
* $ wp secure add_security_headers
310+
* Success: Add Security Headers rule has been deployed.
311+
*
312+
* @when before_wp_load
313+
*/
314+
public function add_security_headers($args, $assoc_args) : void {
315+
(new AddSecurityHeaders($assoc_args))->output();
316+
}
317+
285318
/**
286319
* Removes all WP CLI Secure rules
287320
*
+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
namespace WP_CLI_Secure\SubCommands;
4+
5+
class AddSecurityHeaders extends SubCommand {
6+
public string $ruleTemplate = 'add_security_headers';
7+
public string $ruleName = 'SECURITY HEADERS';
8+
public string $successMessage = 'Add Security Headers rule has been deployed.';
9+
public string $removalMessage= 'Add Security Headers rule has been removed.';
10+
11+
public function getTemplateVars() {
12+
13+
$default_headers = [
14+
'Strict-Transport-Security' => '"max-age=63072000; includeSubDomains; preload"',
15+
'Referrer-Policy' => 'strict-origin-when-cross-origin',
16+
'X-Content-Type-Options' => 'nosniff',
17+
'X-Frame-Options' => 'SAMEORIGIN',
18+
'X-XSS-Protection' => '"1; mode=block"'
19+
];
20+
21+
$headers = isset( $this->commandArguments['headers'] ) ? $this->commandArguments['headers'] : array_keys( $default_headers );
22+
if ( ! empty( $headers ) ) {
23+
if ( is_string( $headers ) ) {
24+
$headers = explode( ',', $headers );
25+
}
26+
$headers = array_map( 'trim', $headers );
27+
28+
foreach ( $headers as $h ) {
29+
$header = '';
30+
$value = '';
31+
foreach ( $default_headers as $key => $v ) {
32+
if ( strtolower( $key ) === strtolower( $h ) ) {
33+
$header = $key;
34+
$value = $v;
35+
}
36+
}
37+
if ( empty( $header ) ) {
38+
continue;
39+
}
40+
$headers_array[] =
41+
[
42+
'header' => $header,
43+
'value' => $value
44+
];
45+
}
46+
return $headers_array;
47+
}
48+
return [];
49+
}
50+
}

src/SubCommands/BlockAccessToSensitiveDirectories.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ public function getTemplateVars() {
2121
if ( ! empty( $directories ) ) {
2222
$directories = explode( ',', $directories );
2323
$directories = array_map( 'trim', $directories );
24-
return [
24+
25+
return [
2526
[ 'directories' => implode( '|', array_map( 'preg_quote', $directories ) ) ]
2627
];
2728
}
29+
2830
return [];
2931
}
3032
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Header always set {{header}} {{value}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
add_header {{header}} {{value}} always;
+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
namespace Tests\Feature;
4+
5+
use Tests\BaseTestCase;
6+
use WP_CLI_Secure\SubCommands\AddSecurityHeaders;
7+
8+
class AddSecurityHeadersTest extends BaseTestCase {
9+
public function setUp(): void {
10+
parent::setUp();
11+
12+
$command = new AddSecurityHeaders($this->nginxAssocArgs);
13+
$command->output();
14+
15+
$command = new AddSecurityHeaders($this->apacheAssocArgs);
16+
$command->output();
17+
18+
exec('cd ' . dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR . $_ENV['WORDPRESS_NGINX_PATH'] . '&& ddev exec nginx -s reload');
19+
}
20+
21+
public function testItWillContainAllHeadersOnNginx() : void {
22+
$response = $this->nginxHttpClient->get('', ['http_errors' => false]);
23+
24+
$this->assertNotEmpty($response->getHeaderLine( 'Strict-Transport-Security' ));
25+
$this->assertNotEmpty($response->getHeaderLine( 'Referrer-Policy' ));
26+
$this->assertNotEmpty($response->getHeaderLine( 'x-content-type-options' ));
27+
$this->assertNotEmpty($response->getHeaderLine( 'X-Frame-Options' ));
28+
$this->assertNotEmpty($response->getHeaderLine( 'X-XSS-Protection' ));
29+
}
30+
31+
public function testItWillContainAllHeadersOnApache() : void {
32+
$response = $this->apacheHttpClient->get('', ['http_errors' => false]);
33+
34+
$this->assertNotEmpty($response->getHeaderLine( 'Strict-Transport-Security' ));
35+
$this->assertNotEmpty($response->getHeaderLine( 'Referrer-Policy' ));
36+
$this->assertNotEmpty($response->getHeaderLine( 'x-content-type-options' ));
37+
$this->assertNotEmpty($response->getHeaderLine( 'X-Frame-Options' ));
38+
$this->assertNotEmpty($response->getHeaderLine( 'X-XSS-Protection' ));
39+
}
40+
}

0 commit comments

Comments
 (0)