Completed
Push — master ( 7eec5f...b860e6 )
by Lorenzo
14:21
created

ComposerSecurityCheck::checkFile()   B

Complexity

Conditions 4
Paths 5

Size

Total Lines 31
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 4

Importance

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