GeneralSecurityCollector::checkSshKeyOnlyLogin()   B
last analyzed

Complexity

Conditions 10
Paths 35

Size

Total Lines 43
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 10
eloc 25
c 1
b 0
f 0
nc 35
nop 0
dl 0
loc 43
rs 7.6666

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Startwind\Inventorio\Collector\System\Security;
4
5
use Startwind\Inventorio\Collector\BasicCollector;
6
use Startwind\Inventorio\Exec\Runner;
7
use Startwind\Inventorio\Exec\System;
8
9
class GeneralSecurityCollector extends BasicCollector
10
{
11
    protected string $identifier = 'SystemSecurity';
12
13
    public function collect(): array
14
    {
15
        $available = $this->isUnattendedUpgradesUsable();
16
        $enabled = false;
17
        if ($available) {
18
            $enabled = $this->isUnattendedUpgradesEnabled();
19
        }
20
21
        $sshOnlyConfig = $this->checkSshKeyOnlyLogin();
22
23
        $result = [
24
            'unattendedUpgradesAvailable' => $available,
25
            'unattendedUpgradesEnabled' => $enabled,
26
            'sshKeyOnlyAvailable' => $sshOnlyConfig['supported'],
27
            'sshKeyOnlyEnabled' => $sshOnlyConfig['enforced'],
28
        ];
29
30
        return $result;
31
    }
32
33
    private function isUnattendedUpgradesEnabled(): bool
34
    {
35
        $configFile = '/etc/apt/apt.conf.d/20auto-upgrades';
36
37
        $runner = Runner::getInstance();
38
39
        if (!$runner->fileExists($configFile)) {
40
            return false;
41
        }
42
43
        $content = $runner->getFileContents($configFile);
44
45
        if ($content === false) {
0 ignored issues
show
introduced by
The condition $content === false is always false.
Loading history...
46
            return false;
47
        }
48
49
        $updateListEnabled = preg_match('/APT::Periodic::Update-Package-Lists\s+"1";/', $content);
50
        $unattendedUpgradeEnabled = preg_match('/APT::Periodic::Unattended-Upgrade\s+"1";/', $content);
51
52
        return $updateListEnabled && $unattendedUpgradeEnabled;
53
    }
54
55
    private function isUnattendedUpgradesUsable(): bool
56
    {
57
        if (stripos(strtolower(System::getInstance()->getPlatform()), 'linux') === false) {
58
            return false;
59
        }
60
61
        $runner = Runner::getInstance();
62
63
        if (!$runner->commandExists('apt')) return false;
64
65
        return !empty($runner->run('apt-cache show unattended-upgrades 2>/dev/null')->getOutput());
66
    }
67
68
    function checkSshKeyOnlyLogin(): array
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
69
    {
70
        $result = ['supported' => false, 'enforced' => false];
71
72
        if (stripos(strtolower(System::getInstance()->getPlatform()), 'linux') === false) {
73
            return $result;
74
        }
75
76
        $runner = Runner::getInstance();
77
78
        $configPath = '/etc/ssh/sshd_config';
79
        if (!$runner->fileExists($configPath)) {
80
            return $result;
81
        }
82
83
        $result['supported'] = true;
84
85
        $config = $runner->getFileContents($configPath);
86
        if ($config === false) {
0 ignored issues
show
introduced by
The condition $config === false is always false.
Loading history...
87
            return $result;
88
        }
89
90
        $lines = preg_split('/\r\n|\r|\n/', $config);
91
        $settings = [];
92
93
        foreach ($lines as $line) {
94
            $line = trim(preg_replace('/#.*/', '', $line)); // Kommentare entfernen
95
            if ($line === '') continue;
96
97
            if (preg_match('/^\s*(\w+)\s+(yes|no)\s*$/i', $line, $matches)) {
98
                $key = strtolower($matches[1]);
99
                $value = strtolower($matches[2]);
100
                $settings[$key] = $value;
101
            }
102
        }
103
104
        $passwordOff = isset($settings['passwordauthentication']) && $settings['passwordauthentication'] === 'no';
105
        $challengeOff = isset($settings['challengeresponseauthentication']) && $settings['challengeresponseauthentication'] === 'no';
0 ignored issues
show
Unused Code introduced by
The assignment to $challengeOff is dead and can be removed.
Loading history...
106
        $usePamOff = isset($settings['usepam']) && $settings['usepam'] === 'no';
0 ignored issues
show
Unused Code introduced by
The assignment to $usePamOff is dead and can be removed.
Loading history...
107
108
        $result['enforced'] = $passwordOff; // && $challengeOff && $usePamOff;
109
110
        return $result;
111
    }
112
}
113