Passed
Push — develop ( 4cc33e...7d04c7 )
by nguereza
02:48
created

SecurityPolicy   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 148
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 55
c 1
b 0
f 0
dl 0
loc 148
rs 10
wmc 13

8 Methods

Rating   Name   Duplication   Size   Complexity  
A hsts() 0 11 2
A clearSiteData() 0 11 2
A features() 0 11 2
A __construct() 0 3 1
A headers() 0 11 1
A nonce() 0 6 1
A commons() 0 11 1
A csp() 0 19 3
1
<?php
2
3
/**
4
 * Platine Framework
5
 *
6
 * Platine Framework is a lightweight, high-performance, simple and elegant PHP
7
 * Web framework
8
 *
9
 * This content is released under the MIT License (MIT)
10
 *
11
 * Copyright (c) 2020 Platine Framework
12
 * Copyright (c) 2015 - 2023 Paragon Initiative Enterprises
13
 *
14
 * Permission is hereby granted, free of charge, to any person obtaining a copy
15
 * of this software and associated documentation files (the "Software"), to deal
16
 * in the Software without restriction, including without limitation the rights
17
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
 * copies of the Software, and to permit persons to whom the Software is
19
 * furnished to do so, subject to the following conditions:
20
 *
21
 * The above copyright notice and this permission notice shall be included in all
22
 * copies or substantial portions of the Software.
23
 *
24
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
 * SOFTWARE.
31
 */
32
33
/**
34
 *  @file SecurityPolicy.php
35
 *
36
 *  The Security Policy class
37
 *
38
 *  @package    Platine\Framework\Security
39
 *  @author Platine Developers team
40
 *  @copyright  Copyright (c) 2020
41
 *  @license    http://opensource.org/licenses/MIT  MIT License
42
 *  @link   https://www.platine-php.com
43
 *  @version 1.0.0
44
 *  @filesource
45
 */
46
47
declare(strict_types=1);
48
49
namespace Platine\Framework\Security;
50
51
use Platine\Framework\Security\Policy\ClearSiteDataPolicy;
52
use Platine\Framework\Security\Policy\ContentSecurityPolicy;
53
use Platine\Framework\Security\Policy\FeaturePermissionPolicy;
54
use Platine\Framework\Security\Policy\StrictTransportSecurityPolicy;
55
56
/**
57
 * @class SecurityPolicy
58
 * @package Platine\Framework\Security
59
 */
60
class SecurityPolicy
61
{
62
    /**
63
     * The configuration
64
     * @var array<string, mixed>
65
     */
66
    protected array $configurations = [];
67
68
    /**
69
     * The nonce's for script-src and style-src
70
     * @var array<string, array<string>>
71
     */
72
    protected array $nonces = [
73
        'style' => [],
74
        'script' => [],
75
    ];
76
77
    /**
78
     * Create new instance
79
     * @param array<string, mixed> $configurations
80
     */
81
    public function __construct(array $configurations = [])
82
    {
83
        $this->configurations = $configurations;
84
    }
85
86
    /**
87
     * Return the headers to be used in response
88
     * @return array<string, string>
89
     */
90
    public function headers(): array
91
    {
92
        $headers = array_merge(
93
            $this->csp(),
94
            $this->features(),
95
            $this->hsts(),
96
            $this->clearSiteData(),
97
            $this->commons()
98
        );
99
100
        return array_filter($headers);
101
    }
102
103
    /**
104
     * Generate random nonce value for current request.
105
     * @param string $target
106
     * @return string
107
     */
108
    public function nonce(string $target = 'script'): string
109
    {
110
        $nonce = base64_encode(bin2hex(random_bytes(8)));
111
        $this->nonces[$target][] = $nonce;
112
113
        return $nonce;
114
    }
115
116
    /**
117
     * Return the Content Security Policy headers
118
     * @return array<string, string>
119
     */
120
    protected function csp(): array
121
    {
122
        $config = $this->configurations['csp'] ?? [];
123
        $isEnabled = $config['enable'] ?? false;
124
        if ($isEnabled === false) {
125
            return [];
126
        }
127
128
        $config['script-src']['nonces'] = $this->nonces['script'];
129
        $config['style-src']['nonces'] = $this->nonces['style'];
130
131
        $isReportOnly = $config['report-only'] ?? false;
132
        $header = $isReportOnly
133
                ? 'Content-Security-Policy-Report-Only'
134
                : 'Content-Security-Policy';
135
136
        $policy = new ContentSecurityPolicy($config);
137
138
        return [$header => $policy->headers()];
139
    }
140
141
    /**
142
     * Return the Permissions Policy headers
143
     * @return array<string, string>
144
     */
145
    protected function features(): array
146
    {
147
        $config = $this->configurations['features-permissions'] ?? [];
148
        $isEnabled = $config['enable'] ?? false;
149
        if ($isEnabled === false) {
150
            return [];
151
        }
152
153
         $policy = new FeaturePermissionPolicy($config);
154
155
        return ['Permissions-Policy' => $policy->headers()];
156
    }
157
158
    /**
159
     * Return the HSTS Policy headers
160
     * @return array<string, string>
161
     */
162
    protected function hsts(): array
163
    {
164
        $config = $this->configurations['hsts'] ?? [];
165
        $isEnabled = $config['enable'] ?? false;
166
        if ($isEnabled === false) {
167
            return [];
168
        }
169
170
         $policy = new StrictTransportSecurityPolicy($config);
171
172
        return ['Strict-Transport-Security' => $policy->headers()];
173
    }
174
175
176
    /**
177
     * Return the Clear Site Data Policy headers
178
     * @return array<string, string>
179
     */
180
    protected function clearSiteData(): array
181
    {
182
        $config = $this->configurations['clear-site-data'] ?? [];
183
        $isEnabled = $config['enable'] ?? false;
184
        if ($isEnabled === false) {
185
            return [];
186
        }
187
188
         $policy = new ClearSiteDataPolicy($config);
189
190
        return ['Clear-Site-Data' => $policy->headers()];
191
    }
192
193
    /**
194
     * Return the common security policies headers
195
     * @return array<string, string>
196
     */
197
    protected function commons(): array
198
    {
199
        return array_filter([
200
            'X-Content-Type-Options' => $this->configurations['x-content-type-options'] ?? 'nosniff',
201
            'X-Download-Options' => $this->configurations['x-download-options'] ?? 'noopen',
202
            'X-Frame-Options' => $this->configurations['x-frame-options'] ?? 'sameorigin',
203
            'X-Permitted-Cross-Domain-Policies' => $this->configurations['x-permitted-cross-domain-policies'] ?? 'none',
204
            'X-Powered-By' => $this->configurations['x-powered-by'] ?? '',
205
            'X-XSS-Protection' => $this->configurations['x-xss-protection'] ?? '1; mode=block',
206
            'Referrer-Policy' => $this->configurations['referrer-policy'] ?? 'no-referrer',
207
            'Server' => $this->configurations['server'] ?? '',
208
        ]);
209
    }
210
}
211