Completed
Push — master ( 1253ef...e4cad3 )
by Lorenzo
06:48
created

ComposerSecurityCheck::handle()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
namespace Padosoft\LaravelComposerSecurity;
4
5
use Illuminate\Console\Command;
6
use GuzzleHttp\Client;
7
use Config;
8
9
10
class ComposerSecurityCheck extends Command
11
{
12
    /**
13
     * The name and signature of the console command.
14
     *
15
     * @var string
16
     */
17
    protected $signature = 'composer-security:check
18
                            {path? : path where find composer.lock, you can use * as jolly character i.e. "/var/www/*/*/", use quotation marks}
19
                            {--M|mail= : If you want send result to email}
20
                            {--N|nomailok=false : True if you want send result to email only for alarm, false is default}
21
                            {--w|whitelist= : If you want exclude from alarm some paths, divide by ","}';
22
23
    /**
24
     * The console command description.
25
     *
26
     * @var string
27
     */
28
    protected $description = <<<EOF
29
The <info>composer-security:check</info> command looks for every composer.lock file in the given path
30
and foreach composer.lock check for security issues in the project dependencies:
31
<info>php composer-security:check</info>
32
If you omit path argument, command look into current folder.
33
You can also pass the path as an argument:
34
<info>php composer-security:check /path/to/my/repos</info>
35
You can use <info>*</info> in path argument as jolly character i.e. <info>/var/www/*/*/</info>
36
By default, the command displays the result in console, but you can also
37
send an html email by using the <info>--mail</info> option:
38
<info>php composer-security:check /path/to/my/repos [email protected]</info>
39
EOF;
40
41
42
    /**
43
     * @var Client an istance of GuzzleHttp\Client
44
     */
45
    protected $guzzle;
46
47
    /**
48
     * @var array
49
     */
50
    protected $headersTableConsole = ['name', 'version', 'title', 'whitelist'];
51
52
    /**
53
     * @var array
54
     */
55
    protected $tableVulnerabilities = [];
56
57
    /**
58
     * Create a new command instance.
59
     *
60
     * @param Client $objguzzle
61
     */
62 12
    public function __construct(Client $objguzzle)
63
    {
64 12
        $this->guzzle = $objguzzle;
65 12
        parent::__construct();
66 12
    }
67
68
    /**
69
     * Execute the console command.
70
     *
71
     * @return mixed
72
     */
73 10
    public function handle()
74
    {
75 10
        $this->hardWork($this->argument(), $this->option());
76 10
    }
77
78
    /**
79
     * @param $argument
80
     * @param $option
81
     */
82 10
    private function hardWork($argument, $option)
83
    {
84 10
        $path = $argument['path'];
85 10
        $this->line('path: <info>' . $path . '</info>.\nCheck composer.lock files...');
86 10
        $lockFiles = $this->findFilesComposerLock($path);
87 10
        $this->line('Find <info>' . count($lockFiles) . '</info> composer.lock files.');
88
89 10
        $this->tableVulnerabilities = [];
90 10
        $tuttoOk = true;
91 10
        $numLock = 0;
92
93 10
        $whitelist = FileHelper::adjustPath($option['whitelist']);
94
95 10
        foreach ($lockFiles as $fileLock) {
96
97 10
            $this->line("Analizing <info>" . ($numLock + 1) . "</info> di <info>" . count($lockFiles) . "</info>");
98
99 10
            $tuttoOk = $this->checkFile($fileLock, $whitelist);
100
101 10
            $numLock++;
102 10
        }
103
104 10
        $this->notifyResult($option['mail'], $option['nomailok'], $tuttoOk);
105
106 10
    }
107
108
    /**
109
     * @param $mail
110
     * @param $tuttoOk
111
     */
112 10
    private function notifyResult($mail, $nomailok, $tuttoOk)
113
    {
114
115
        //print to console
116 10
        $this->table($this->headersTableConsole, $this->tableVulnerabilities);
117
118
        //send email
119 10
        if(!$nomailok || !$tuttoOk) {
120 2
            $this->sendEmail($mail, $tuttoOk);
121 2
        }
122
123 10
        if ($tuttoOk) {
124 8
            return $this->notifyOK();
125
        }
126
127 2
        $this->notifyKO();
128 2
    }
129
130
131 8
    private function notifyOK()
132
    {
133 8
        $esito = Config::get('composer-security-check.mailSubjectSuccess');
134 8
        $this->line($esito);
135 8
    }
136
137 2
    private function notifyKO()
138
    {
139 2
        $esito = Config::get('composer-security-check.mailSubjetcAlarm');
140 2
        $this->error($esito);
141 2
    }
142
143
    /**
144
     * @param $mail
145
     * @param $tuttoOk
146
     */
147 2
    private function sendEmail($mail, $tuttoOk)
148
    {
149 2
        if ($mail != '') {
150 2
            $email = new MailHelper($this);
151 2
            $email->sendEmail($tuttoOk, $mail, $this->tableVulnerabilities);
152 2
        }
153 2
    }
154
155
    /**
156
     *
157
     * @param $path
158
     * @return array of composer.lock file
159
     */
160 12
    private function findFilesComposerLock($path)
161
    {
162 12
        $file = new FileHelper();
163 12
        $lockFiles = array();
164 12
        foreach ($file->adjustPath($path) as $item) {
165 12
            $lockFiles = array_merge($lockFiles,$file->findFiles($item, 'composer.lock'));
166 12
        }
167
168
169 12
        if(!is_array($lockFiles)){
170
            $lockFiles = array();
171
        }
172
173 12
        return $lockFiles;
174
    }
175
176
    /**
177
     * @param $fileLock
178
     * @param $whitelist
179
     * @return bool
180
     */
181 10
    private function checkFile($fileLock, $whitelist)
182
    {
183 10
        $this->line("Analizing: $fileLock ...");
184
185 10
        $this->tableVulnerabilities[] = [
186 10
            'name' => $fileLock,
187 10
            'version' => '',
188 10
            'advisories' => '',
189
            'isOk' => ''
190 10
        ];
191
192 10
        $sensiolab = new SensiolabHelper($this->guzzle, $this);
193 10
        $response = $sensiolab->getSensiolabVulnerabilties($fileLock);
194
195 10
        if (($response === null) | !is_array($response)) {
196
            $this->error("Errore Response not vaild or null.");
197
            return true;
198
        }
199 10
        if (count($response) == 0) {
200 6
            return true;
201
        }
202 6
        $this->error("Trovate " . count($response) . " vulnerabilita' in $fileLock");
203
204 6
        $tuttoOk = in_array(rtrim(str_replace('\\', '/', $fileLock), 'composer.lock'), $whitelist);
205
206 6
        foreach ($response as $key => $vulnerability) {
207
208 6
            $this->tableVulnerabilities = array_merge($this->tableVulnerabilities, $sensiolab->checkResponse($key, $vulnerability, $tuttoOk));
209 6
        }
210
211 6
        return $tuttoOk;
212
    }
213
214
}
215
216