Test Failed
Push — master ( a6fea0...d3a109 )
by Antonio Carlos
03:01
created

Certificate::getResourceUrlArray()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace PragmaRX\Health\Checkers;
4
5
use Illuminate\Support\Str;
6
use Illuminate\Support\Collection;
7
use PragmaRX\Health\Support\Result;
8
use Spatie\SslCertificate\SslCertificate;
9
10
class Certificate extends Base
11
{
12
    /**
13
     * HTTP Checker.
14
     *
15
     * @return Result
16
     */
17
    public function check()
18
    {
19
        $resources = $this->getResourceUrlArray();
20
21
        $first = collect($resources)->first();
22
23
        if (filled($first)) {
24
            $this->target->setDisplay("{$first}");
25
        }
26
27
        try {
28
            foreach ($resources as $url) {
29
                [$healthy, $message] = $this->checkCertificate($url);
30
31
                if (!$healthy) {
32
                    return $this->makeResult(false, $message);
33
                }
34
            }
35
36
            return $this->makeHealthyResult();
37
        } catch (\Exception $exception) {
38
            report($exception);
39
40
            return $this->makeResultFromException($exception);
41
        }
42
    }
43
44
    /**
45
     * HTTP Checker.
46
     *
47
     * @return Result
48
     */
49
    public function checkCertificate($url)
50
    {
51
        return $this->checkHostCertificate($this->getHost($url));
52
    }
53
54
    /**
55
     * Get the error message.
56
     *
57
     * @return string
58
     */
59
    protected function getErrorMessage($host)
60
    {
61
        return sprintf($this->target->resource->errorMessage, $host);
62
    }
63
64
    /**
65
     * Get the error message.
66
     *
67
     * @return string
68
     */
69
    protected function getHost($url)
70
    {
71
        $parsed = parse_url($url);
72
73
        if (isset($parsed['host'])) {
74
            return $parsed['host'];
75
        }
76
77
        return $url;
78
    }
79
80
    /**
81
     *  Get array of resource urls.
82
     *
83
     * @return array
84
     */
85
    private function getResourceUrlArray()
86
    {
87
        if (is_a($this->target->urls, Collection::class)) {
88
            return $this->target->urls->toArray();
89
        }
90
91
        return (array) $this->target->urls;
92
    }
93
94
    public function checkHostCertificate($host)
95
    {
96
        $result = collect([
97
            'openssl' => $this->checkCertificateWithOpenSSL($host),
98
99
            'package' => [
100
                SslCertificate::createForHostName($host)->isValid(),
101
                'Invalid certificate'
102
            ],
103
104
            'php' => $this->checkCertificateWithPhp($host)
105
        ])
106
            ->filter(fn($result) => $result[0] === false)
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_DOUBLE_ARROW, expecting ',' or ')'
Loading history...
107
            ->first();
108
109
        if ($result === null) {
110
            return [true, ''];
111
        }
112
113
        return $result;
114
    }
115
116
    public function checkCertificateWithOpenSSL($host)
117
    {
118
        exec($this->makeCommand($host), $output);
119
120
        $result = collect($output)
121
            ->filter(
122
                fn($line) => Str::contains(
123
                    $line,
124
                    $this->target->resource->verifyString
125
                )
126
            )
127
            ->first();
128
129
        if (blank($result)) {
130
            $output = blank($output) ? 'Unkown openssl error' : $output;
131
132
            return [false, json_encode($output)];
133
        }
134
135
        return [
136
            trim($result) == $this->target->resource->successString,
137
            $result
138
        ];
139
    }
140
141
    public function checkCertificateWithPhp($host)
142
    {
143
        try {
144
            $get = stream_context_create([
145
                'ssl' => ['capture_peer_cert' => true]
146
            ]);
147
148
            $read = stream_socket_client(
149
                'ssl://' . $host . ':443',
150
                $errno,
151
                $errstr,
152
                30,
153
                STREAM_CLIENT_CONNECT,
154
                $get
155
            );
156
        } catch (\Exception $exception) {
157
            return [false, $exception->getMessage()];
158
        }
159
160
        return [true, ''];
161
    }
162
163
    /**
164
     * @param $host
165
     * @return string|string[]
166
     */
167
    protected function makeCommand($host)
168
    {
169
        $command = $this->target->resource->command;
170
171
        $command = str_replace('{$options}', $this->target->options, $command);
172
173
        $command = str_replace('{$host}', $host, $command);
174
175
        return $command;
176
    }
177
}
178